diff options
Diffstat (limited to 'src/3rdparty/webkit/WebCore/bindings')
57 files changed, 1100 insertions, 446 deletions
diff --git a/src/3rdparty/webkit/WebCore/bindings/ScriptControllerBase.cpp b/src/3rdparty/webkit/WebCore/bindings/ScriptControllerBase.cpp index 4d73d83..7dc68ef 100644 --- a/src/3rdparty/webkit/WebCore/bindings/ScriptControllerBase.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/ScriptControllerBase.cpp @@ -53,6 +53,7 @@ ScriptValue ScriptController::executeScript(const ScriptSourceCode& sourceCode) return result; } + bool ScriptController::executeIfJavaScriptURL(const KURL& url, bool userGesture, bool replaceDocument) { if (!protocolIsJavaScript(url)) @@ -61,6 +62,9 @@ bool ScriptController::executeIfJavaScriptURL(const KURL& url, bool userGesture, if (m_frame->page() && !m_frame->page()->javaScriptURLsAreAllowed()) return true; + if (m_frame->inViewSourceMode()) + return true; + const int javascriptSchemeLength = sizeof("javascript:") - 1; String script = decodeURLEscapeSequences(url.string().substring(javascriptSchemeLength)); diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSAbstractWorkerCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSAbstractWorkerCustom.cpp index a6cbd91..6eca7bd 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSAbstractWorkerCustom.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSAbstractWorkerCustom.cpp @@ -50,7 +50,7 @@ JSValue JSAbstractWorker::addEventListener(ExecState* exec, const ArgList& args) if (!listener.isObject()) return jsUndefined(); - impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false), args.at(2).toBoolean(exec)); + impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)), args.at(2).toBoolean(exec)); return jsUndefined(); } @@ -60,7 +60,7 @@ JSValue JSAbstractWorker::removeEventListener(ExecState* exec, const ArgList& ar if (!listener.isObject()) return jsUndefined(); - impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec)); + impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); return jsUndefined(); } diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSBindingsAllInOne.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSBindingsAllInOne.cpp new file mode 100644 index 0000000..f08303a --- /dev/null +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSBindingsAllInOne.cpp @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2009 Apple 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: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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. + */ + +// This all-in-one cpp file cuts down on template bloat to allow us to build our Windows release build. + +#include "GCController.cpp" +#include "JSAbstractWorkerCustom.cpp" +#include "JSAttrCustom.cpp" +#include "JSAudioConstructor.cpp" +#include "JSCDATASectionCustom.cpp" +#include "JSCSSRuleCustom.cpp" +#include "JSCSSRuleListCustom.cpp" +#include "JSCSSStyleDeclarationCustom.cpp" +#include "JSCSSValueCustom.cpp" +#include "JSCallbackData.cpp" +#include "JSCanvasRenderingContext2DCustom.cpp" +#include "JSCanvasRenderingContextCustom.cpp" +#include "JSClipboardCustom.cpp" +#include "JSConsoleCustom.cpp" +#include "JSCoordinatesCustom.cpp" +#include "JSCustomSQLStatementCallback.cpp" +#include "JSCustomSQLStatementErrorCallback.cpp" +#include "JSCustomSQLTransactionCallback.cpp" +#include "JSCustomSQLTransactionErrorCallback.cpp" +#include "JSCustomVoidCallback.cpp" +#include "JSCustomXPathNSResolver.cpp" +#include "JSDOMApplicationCacheCustom.cpp" +#include "JSDOMBinding.cpp" +#include "JSDOMGlobalObject.cpp" +#include "JSDOMWindowBase.cpp" +#include "JSDOMWindowCustom.cpp" +#include "JSDOMWindowShell.cpp" +#include "JSDataGridColumnListCustom.cpp" +#include "JSDataGridDataSource.cpp" +#include "JSDatabaseCustom.cpp" +#include "JSDedicatedWorkerContextCustom.cpp" +#include "JSDesktopNotificationsCustom.cpp" +#include "JSDocumentCustom.cpp" +#include "JSDocumentFragmentCustom.cpp" +#include "JSElementCustom.cpp" +#include "JSEventCustom.cpp" +#include "JSEventListener.cpp" +#include "JSEventSourceConstructor.cpp" +#include "JSEventSourceCustom.cpp" +#include "JSEventTarget.cpp" +#include "JSExceptionBase.cpp" +#include "JSHTMLAllCollectionCustom.cpp" +#include "JSHTMLAppletElementCustom.cpp" +#include "JSHTMLCanvasElementCustom.cpp" +#include "JSHTMLCollectionCustom.cpp" +#include "JSHTMLDataGridElementCustom.cpp" +#include "JSHTMLDocumentCustom.cpp" +#include "JSHTMLElementCustom.cpp" +#include "JSHTMLEmbedElementCustom.cpp" +#include "JSHTMLFormElementCustom.cpp" +#include "JSHTMLFrameElementCustom.cpp" +#include "JSHTMLFrameSetElementCustom.cpp" +#include "JSHTMLIFrameElementCustom.cpp" +#include "JSHTMLInputElementCustom.cpp" +#include "JSHTMLObjectElementCustom.cpp" +#include "JSHTMLOptionsCollectionCustom.cpp" +#include "JSHTMLSelectElementCustom.cpp" +#include "JSHistoryCustom.cpp" +#include "JSImageConstructor.cpp" +#include "JSImageDataCustom.cpp" +#include "JSInspectedObjectWrapper.cpp" +#include "JSInspectorBackendCustom.cpp" +#include "JSJavaScriptCallFrameCustom.cpp" +#include "JSLazyEventListener.cpp" +#include "JSLocationCustom.cpp" +#include "JSMessageChannelConstructor.cpp" +#include "JSMessageChannelCustom.cpp" +#include "JSMessageEventCustom.cpp" +#include "JSMessagePortCustom.cpp" +#include "JSMimeTypeArrayCustom.cpp" +#include "JSNamedNodeMapCustom.cpp" +#include "JSNavigatorCustom.cpp" +#include "JSNodeCustom.cpp" +#include "JSNodeFilterCondition.cpp" +#include "JSNodeFilterCustom.cpp" +#include "JSNodeIteratorCustom.cpp" +#include "JSNodeListCustom.cpp" +#include "JSOptionConstructor.cpp" +#include "JSPluginArrayCustom.cpp" +#include "JSPluginCustom.cpp" +#include "JSPluginElementFunctions.cpp" +#include "JSQuarantinedObjectWrapper.cpp" +#include "JSSQLResultSetRowListCustom.cpp" +#include "JSSQLTransactionCustom.cpp" +#include "JSSVGElementInstanceCustom.cpp" +#include "JSSVGLengthCustom.cpp" +#include "JSSVGMatrixCustom.cpp" +#include "JSSVGPathSegCustom.cpp" +#include "JSSVGPathSegListCustom.cpp" +#include "JSSVGPointListCustom.cpp" +#include "JSSharedWorkerConstructor.cpp" +#include "JSSharedWorkerCustom.cpp" +#include "JSStorageCustom.cpp" +#include "JSStyleSheetCustom.cpp" +#include "JSStyleSheetListCustom.cpp" +#include "JSTextCustom.cpp" +#include "JSTreeWalkerCustom.cpp" +#include "JSWebKitCSSMatrixConstructor.cpp" +#include "JSWebKitPointConstructor.cpp" +#include "JSWebSocketConstructor.cpp" +#include "JSWebSocketCustom.cpp" +#include "JSWorkerConstructor.cpp" +#include "JSWorkerContextBase.cpp" +#include "JSWorkerContextCustom.cpp" +#include "JSWorkerCustom.cpp" +#include "JSXMLHttpRequestConstructor.cpp" +#include "JSXMLHttpRequestCustom.cpp" +#include "JSXMLHttpRequestUploadCustom.cpp" +#include "JSXSLTProcessorConstructor.cpp" +#include "JSXSLTProcessorCustom.cpp" +#include "ScheduledAction.cpp" +#include "ScriptArray.cpp" +#include "ScriptCachedFrameData.cpp" +#include "ScriptCallFrame.cpp" +#include "ScriptCallStack.cpp" +#include "ScriptController.cpp" +#include "ScriptControllerWin.cpp" +#include "ScriptEventListener.cpp" +#include "ScriptFunctionCall.cpp" +#include "ScriptObjectQuarantine.cpp" +#include "ScriptState.cpp" +#include "SerializedScriptValue.cpp" +#include "WorkerScriptController.cpp" diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSCallbackData.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSCallbackData.cpp index d08f760..38292c7 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSCallbackData.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSCallbackData.cpp @@ -48,7 +48,12 @@ JSValue JSCallbackData::invokeCallback(MarkedArgumentBuffer& args, bool* raisedE ExecState* exec = globalObject()->globalExec(); - JSValue function = callback()->get(exec, Identifier(exec, "handleEvent")); + JSValue function; + { + // Switch worlds, just in case handleEvent is a getter and causes JS execution! + EnterDOMWrapperWorld worldEntry(exec, m_isolatedWorld.get()); + function = callback()->get(exec, Identifier(exec, "handleEvent")); + } CallData callData; CallType callType = function.getCallData(callData); if (callType == CallTypeNone) { @@ -59,7 +64,7 @@ JSValue JSCallbackData::invokeCallback(MarkedArgumentBuffer& args, bool* raisedE } globalObject()->globalData()->timeoutChecker.start(); - JSValue result = call(exec, function, callType, callData, callback(), args); + JSValue result = callInWorld(exec, function, callType, callData, callback(), args, m_isolatedWorld.get()); globalObject()->globalData()->timeoutChecker.stop(); Document::updateStyleForAllDocuments(); diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSCallbackData.h b/src/3rdparty/webkit/WebCore/bindings/js/JSCallbackData.h index 4fc9f84..5c86701 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSCallbackData.h +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSCallbackData.h @@ -29,6 +29,7 @@ #ifndef JSCallbackData_h #define JSCallbackData_h +#include "JSDOMBinding.h" #include "JSDOMGlobalObject.h" #include <runtime/JSObject.h> #include <runtime/Protect.h> @@ -47,6 +48,7 @@ public: JSCallbackData(JSC::JSObject* callback, JSDOMGlobalObject* globalObject) : m_callback(callback) , m_globalObject(globalObject) + , m_isolatedWorld(currentWorld(globalObject->globalExec())) { } @@ -63,6 +65,7 @@ public: private: JSC::ProtectedPtr<JSC::JSObject> m_callback; JSC::ProtectedPtr<JSDOMGlobalObject> m_globalObject; + RefPtr<DOMWrapperWorld> m_isolatedWorld; }; } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSCustomXPathNSResolver.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSCustomXPathNSResolver.cpp index da4a53a..c2884d7 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSCustomXPathNSResolver.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSCustomXPathNSResolver.cpp @@ -90,7 +90,7 @@ String JSCustomXPathNSResolver::lookupNamespaceURI(const String& prefix) args.append(jsString(exec, prefix)); m_globalObject->globalData()->timeoutChecker.start(); - JSValue retval = call(exec, function, callType, callData, m_customResolver, args); + JSValue retval = callInWorld(exec, function, callType, callData, m_customResolver, args, currentWorld(m_globalObject->globalExec())); m_globalObject->globalData()->timeoutChecker.stop(); String result; diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMApplicationCacheCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMApplicationCacheCustom.cpp index 8634589..91ee51a 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMApplicationCacheCustom.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMApplicationCacheCustom.cpp @@ -91,7 +91,7 @@ JSValue JSDOMApplicationCache::addEventListener(ExecState* exec, const ArgList& if (!listener.isObject()) return jsUndefined(); - impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false), args.at(2).toBoolean(exec)); + impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)), args.at(2).toBoolean(exec)); return jsUndefined(); } @@ -101,7 +101,7 @@ JSValue JSDOMApplicationCache::removeEventListener(ExecState* exec, const ArgLis if (!listener.isObject()) return jsUndefined(); - impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec)); + impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); return jsUndefined(); } diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMBinding.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMBinding.cpp index 8168323..ef69c7b 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMBinding.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMBinding.cpp @@ -21,6 +21,8 @@ #include "config.h" #include "JSDOMBinding.h" +#include "debugger/DebuggerCallFrame.h" + #include "ActiveDOMObject.h" #include "DOMCoreException.h" #include "Document.h" @@ -44,6 +46,7 @@ #include "MessagePort.h" #include "RangeException.h" #include "ScriptController.h" +#include "Settings.h" #include "XMLHttpRequestException.h" #include <runtime/Error.h> #include <runtime/JSFunction.h> @@ -72,6 +75,7 @@ namespace WebCore { using namespace HTMLNames; typedef Document::JSWrapperCache JSWrapperCache; +typedef Document::JSWrapperCacheMap JSWrapperCacheMap; // 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 @@ -80,6 +84,7 @@ typedef Document::JSWrapperCache JSWrapperCache; static void addWrapper(DOMObject* wrapper); static void removeWrapper(DOMObject* wrapper); static void removeWrappers(const JSWrapperCache& wrappers); +static void removeWrappers(const DOMObjectWrapperMap& wrappers); #ifdef NDEBUG @@ -95,6 +100,10 @@ static inline void removeWrappers(const JSWrapperCache&) { } +static inline void removeWrappers(const DOMObjectWrapperMap&) +{ +} + #else static HashSet<DOMObject*>& wrapperSet() @@ -124,7 +133,15 @@ static void removeWrapper(DOMObject* wrapper) static void removeWrappers(const JSWrapperCache& wrappers) { - for (JSWrapperCache::const_iterator it = wrappers.begin(); it != wrappers.end(); ++it) + JSWrapperCache::const_iterator wrappersEnd = wrappers.end(); + for (JSWrapperCache::const_iterator it = wrappers.begin(); it != wrappersEnd; ++it) + removeWrapper(it->second); +} + +static inline void removeWrappers(const DOMObjectWrapperMap& wrappers) +{ + DOMObjectWrapperMap::const_iterator wrappersEnd = wrappers.end(); + for (DOMObjectWrapperMap::const_iterator it = wrappers.begin(); it != wrappersEnd; ++it) removeWrapper(it->second); } @@ -135,67 +152,120 @@ DOMObject::~DOMObject() #endif -class DOMObjectWrapperMap { -public: - static DOMObjectWrapperMap& mapFor(JSGlobalData&); +DOMWrapperWorld::DOMWrapperWorld(JSC::JSGlobalData* globalData) + : m_globalData(globalData) +{ +} + +DOMWrapperWorld::~DOMWrapperWorld() +{ + JSGlobalData::ClientData* clientData = m_globalData->clientData; + ASSERT(clientData); + static_cast<WebCoreJSClientData*>(clientData)->forgetWorld(this); + + removeWrappers(m_wrappers); - DOMObject* get(void* objectHandle) + for (HashSet<Document*>::iterator iter = documentsWithWrappers.begin(); iter != documentsWithWrappers.end(); ++iter) + forgetWorldOfDOMNodesForDocument(*iter, this); + for (HashSet<ScriptController*>::iterator iter = scriptControllersWithShells.begin(); iter != scriptControllersWithShells.end(); ++iter) + (*iter)->forgetWorld(this); +} + +EnterDOMWrapperWorld::EnterDOMWrapperWorld(JSC::JSGlobalData& globalData, DOMWrapperWorld* isolatedWorld) +{ + JSGlobalData::ClientData* clientData = globalData.clientData; + ASSERT(clientData); + m_clientData = static_cast<WebCoreJSClientData*>(clientData); + m_clientData->m_worldStack.append(isolatedWorld); +} + +EnterDOMWrapperWorld::EnterDOMWrapperWorld(JSC::ExecState* exec, DOMWrapperWorld* isolatedWorld) +{ + JSGlobalData::ClientData* clientData = exec->globalData().clientData; + ASSERT(clientData); + m_clientData = static_cast<WebCoreJSClientData*>(clientData); + m_clientData->m_worldStack.append(isolatedWorld); +} + +EnterDOMWrapperWorld::~EnterDOMWrapperWorld() +{ + m_clientData->m_worldStack.removeLast(); +} + +class JSGlobalDataWorldIterator { +public: + JSGlobalDataWorldIterator(JSGlobalData* globalData) + : m_pos(static_cast<WebCoreJSClientData*>(globalData->clientData)->m_worldSet.begin()) + , m_end(static_cast<WebCoreJSClientData*>(globalData->clientData)->m_worldSet.end()) { - return m_map.get(objectHandle); } - void set(void* objectHandle, DOMObject* wrapper) + operator bool() { - addWrapper(wrapper); - m_map.set(objectHandle, wrapper); + return m_pos != m_end; } - void remove(void* objectHandle) + DOMWrapperWorld* operator*() { - removeWrapper(m_map.take(objectHandle)); + ASSERT(m_pos != m_end); + return *m_pos; } -private: - HashMap<void*, DOMObject*> m_map; -}; - -// Map from static HashTable instances to per-GlobalData ones. -class DOMObjectHashTableMap { -public: - static DOMObjectHashTableMap& mapFor(JSGlobalData&); - - ~DOMObjectHashTableMap() + DOMWrapperWorld* operator->() { - 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(); + ASSERT(m_pos != m_end); + return *m_pos; } - const JSC::HashTable* get(const JSC::HashTable* staticTable) + JSGlobalDataWorldIterator& operator++() { - 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; + ++m_pos; + return *this; } private: - HashMap<const JSC::HashTable*, JSC::HashTable> m_map; + HashSet<DOMWrapperWorld*>::iterator m_pos; + HashSet<DOMWrapperWorld*>::iterator m_end; }; -class WebCoreJSClientData : public JSGlobalData::ClientData { -public: - DOMObjectHashTableMap hashTableMap; - DOMObjectWrapperMap wrapperMap; -}; +static inline DOMWrapperWorld* currentWorld(JSC::JSGlobalData& globalData) +{ + JSGlobalData::ClientData* clientData = globalData.clientData; + ASSERT(clientData); + return static_cast<WebCoreJSClientData*>(clientData)->currentWorld(); +} + +DOMWrapperWorld* currentWorld(JSC::ExecState* exec) +{ + return currentWorld(exec->globalData()); +} + +DOMWrapperWorld* normalWorld(JSC::JSGlobalData& globalData) +{ + JSGlobalData::ClientData* clientData = globalData.clientData; + ASSERT(clientData); + return static_cast<WebCoreJSClientData*>(clientData)->normalWorld(); +} + +DOMWrapperWorld* mainThreadNormalWorld() +{ + ASSERT(isMainThread()); + return normalWorld(*JSDOMWindow::commonJSGlobalData()); +} + +DOMWrapperWorld* mainThreadCurrentWorld() +{ + ASSERT(isMainThread()); + + JSGlobalData::ClientData* clientData = JSDOMWindowBase::commonJSGlobalData()->clientData; + ASSERT(clientData); + return static_cast<WebCoreJSClientData*>(clientData)->currentWorld(); +} DOMObjectHashTableMap& DOMObjectHashTableMap::mapFor(JSGlobalData& globalData) { JSGlobalData::ClientData* clientData = globalData.clientData; - if (!clientData) { - clientData = new WebCoreJSClientData; - globalData.clientData = clientData; - } + ASSERT(clientData); return static_cast<WebCoreJSClientData*>(clientData)->hashTableMap; } @@ -204,64 +274,102 @@ const JSC::HashTable* getHashTableForGlobalData(JSGlobalData& globalData, const return DOMObjectHashTableMap::mapFor(globalData).get(staticTable); } -inline DOMObjectWrapperMap& DOMObjectWrapperMap::mapFor(JSGlobalData& globalData) +//inline DOMObjectWrapperMap& DOMObjectWrapperMap::mapFor(JSGlobalData& globalData) +inline DOMObjectWrapperMap& DOMObjectWrapperMapFor(JSGlobalData& globalData) { - JSGlobalData::ClientData* clientData = globalData.clientData; - if (!clientData) { - clientData = new WebCoreJSClientData; - globalData.clientData = clientData; - } - return static_cast<WebCoreJSClientData*>(clientData)->wrapperMap; + return currentWorld(globalData)->m_wrappers; } DOMObject* getCachedDOMObjectWrapper(JSGlobalData& globalData, void* objectHandle) { - return DOMObjectWrapperMap::mapFor(globalData).get(objectHandle); + return DOMObjectWrapperMapFor(globalData).get(objectHandle); } void cacheDOMObjectWrapper(JSGlobalData& globalData, void* objectHandle, DOMObject* wrapper) { - DOMObjectWrapperMap::mapFor(globalData).set(objectHandle, wrapper); + addWrapper(wrapper); + DOMObjectWrapperMapFor(globalData).set(objectHandle, wrapper); } -void forgetDOMObject(JSGlobalData& globalData, void* objectHandle) +JSNode* getCachedDOMNodeWrapper(Document* document, Node* node) { - DOMObjectWrapperMap::mapFor(globalData).remove(objectHandle); + if (document) + return document->getWrapperCache(mainThreadCurrentWorld())->get(node); + return static_cast<JSNode*>(DOMObjectWrapperMapFor(*JSDOMWindow::commonJSGlobalData()).get(node)); } -JSNode* getCachedDOMNodeWrapper(Document* document, Node* node) +void forgetDOMObject(DOMObject* wrapper, void* objectHandle) { - if (!document) - return static_cast<JSNode*>(DOMObjectWrapperMap::mapFor(*JSDOMWindow::commonJSGlobalData()).get(node)); - return document->wrapperCache().get(node); + JSC::JSGlobalData* globalData = Heap::heap(wrapper)->globalData(); + for (JSGlobalDataWorldIterator worldIter(globalData); worldIter; ++worldIter) { + DOMObjectWrapperMap& wrappers = worldIter->m_wrappers; + DOMObjectWrapperMap::iterator iter = wrappers.find(objectHandle); + if ((iter != wrappers.end()) && (iter->second == wrapper)) { + removeWrapper(wrapper); + wrappers.remove(iter); + return; + } + } + + // If the world went away, it should have removed this wrapper from the set. + ASSERT(!wrapperSet().contains(wrapper)); } -void forgetDOMNode(Document* document, Node* node) +void forgetDOMNode(DOMObject* wrapper, Node* node, Document* document) { if (!document) { - DOMObjectWrapperMap::mapFor(*JSDOMWindow::commonJSGlobalData()).remove(node); + forgetDOMObject(wrapper, node); return; } - removeWrapper(document->wrapperCache().take(node)); + + JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap(); + for (JSWrapperCacheMap::iterator wrappersIter = wrapperCacheMap.begin(); wrappersIter != wrapperCacheMap.end(); ++wrappersIter) { + JSWrapperCache* wrappers = wrappersIter->second; + JSWrapperCache::iterator iter = wrappers->find(node); + if ((iter != wrappers->end()) && (iter->second == wrapper)) { + wrappers->remove(iter); + removeWrapper(wrapper); + return; + } + } + + // If the world went away, it should have removed this wrapper from the set. + ASSERT(!wrapperSet().contains(wrapper)); } void cacheDOMNodeWrapper(Document* document, Node* node, JSNode* wrapper) { if (!document) { - DOMObjectWrapperMap::mapFor(*JSDOMWindow::commonJSGlobalData()).set(node, wrapper); + addWrapper(wrapper); + DOMObjectWrapperMapFor(*JSDOMWindow::commonJSGlobalData()).set(node, wrapper); return; } addWrapper(wrapper); - document->wrapperCache().set(node, wrapper); + document->getWrapperCache(mainThreadCurrentWorld())->set(node, wrapper); } void forgetAllDOMNodesForDocument(Document* document) { ASSERT(document); - removeWrappers(document->wrapperCache()); + JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap(); + JSWrapperCacheMap::const_iterator wrappersMapEnd = wrapperCacheMap.end(); + for (JSWrapperCacheMap::const_iterator wrappersMapIter = wrapperCacheMap.begin(); wrappersMapIter != wrappersMapEnd; ++wrappersMapIter) { + JSWrapperCache* wrappers = wrappersMapIter->second; + removeWrappers(*wrappers); + delete wrappers; + wrappersMapIter->first->forgetDocument(document); + } +} + +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'! + removeWrappers(*wrappers); + delete wrappers; } -static inline bool isObservableThroughDOM(JSNode* jsNode) +static inline bool isObservableThroughDOM(JSNode* jsNode, DOMWrapperWorld* world) { // Certain conditions implicitly make a JS DOM node wrapper observable // through the DOM, even if no explicit reference to it remains. @@ -287,14 +395,14 @@ static inline bool isObservableThroughDOM(JSNode* jsNode) // the custom markChildren functions rather than here. if (node->isElementNode()) { if (NamedNodeMap* attributes = static_cast<Element*>(node)->attributeMap()) { - if (DOMObject* wrapper = getCachedDOMObjectWrapper(*jsNode->globalObject()->globalData(), attributes)) { + if (DOMObject* wrapper = world->m_wrappers.get(attributes)) { if (wrapper->hasCustomProperties()) return true; } } if (node->isStyledElement()) { if (CSSMutableStyleDeclaration* style = static_cast<StyledElement*>(node)->inlineStyleDecl()) { - if (DOMObject* wrapper = getCachedDOMObjectWrapper(*jsNode->globalObject()->globalData(), style)) { + if (DOMObject* wrapper = world->m_wrappers.get(style)) { if (wrapper->hasCustomProperties()) return true; } @@ -302,7 +410,7 @@ static inline bool isObservableThroughDOM(JSNode* jsNode) } if (static_cast<Element*>(node)->hasTagName(canvasTag)) { if (CanvasRenderingContext* context = static_cast<HTMLCanvasElement*>(node)->renderingContext()) { - if (DOMObject* wrapper = getCachedDOMObjectWrapper(*jsNode->globalObject()->globalData(), context)) { + if (DOMObject* wrapper = world->m_wrappers.get(context)) { if (wrapper->hasCustomProperties()) return true; } @@ -333,14 +441,19 @@ static inline bool isObservableThroughDOM(JSNode* jsNode) return false; } -void markDOMNodesForDocument(MarkStack& markStack, Document* doc) +void markDOMNodesForDocument(MarkStack& markStack, Document* document) { - JSWrapperCache& nodeDict = doc->wrapperCache(); - JSWrapperCache::iterator nodeEnd = nodeDict.end(); - for (JSWrapperCache::iterator nodeIt = nodeDict.begin(); nodeIt != nodeEnd; ++nodeIt) { - JSNode* jsNode = nodeIt->second; - if (isObservableThroughDOM(jsNode)) - markStack.append(jsNode); + JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap(); + for (JSWrapperCacheMap::iterator wrappersIter = wrapperCacheMap.begin(); wrappersIter != wrapperCacheMap.end(); ++wrappersIter) { + DOMWrapperWorld* world = wrappersIter->first; + JSWrapperCache* nodeDict = wrappersIter->second; + + JSWrapperCache::iterator nodeEnd = nodeDict->end(); + for (JSWrapperCache::iterator nodeIt = nodeDict->begin(); nodeIt != nodeEnd; ++nodeIt) { + JSNode* jsNode = nodeIt->second; + if (isObservableThroughDOM(jsNode, world)) + markStack.append(jsNode); + } } } @@ -353,12 +466,10 @@ void markActiveObjectsForContext(MarkStack& markStack, JSGlobalData& globalData, HashMap<ActiveDOMObject*, void*>::const_iterator activeObjectsEnd = activeObjects.end(); for (HashMap<ActiveDOMObject*, void*>::const_iterator iter = activeObjects.begin(); iter != activeObjectsEnd; ++iter) { if (iter->first->hasPendingActivity()) { - DOMObject* wrapper = getCachedDOMObjectWrapper(globalData, iter->second); // Generally, an active object with pending activity must have a wrapper to mark its listeners. // However, some ActiveDOMObjects don't have JS wrappers (timers created by setTimeout is one example). // FIXME: perhaps need to make sure even timers have a markable 'wrapper'. - if (wrapper) - markStack.append(wrapper); + markDOMObjectWrapper(markStack, globalData, iter->second); } } @@ -366,10 +477,31 @@ void markActiveObjectsForContext(MarkStack& markStack, JSGlobalData& globalData, HashSet<MessagePort*>::const_iterator portsEnd = messagePorts.end(); for (HashSet<MessagePort*>::const_iterator iter = messagePorts.begin(); iter != portsEnd; ++iter) { // If the message port is remotely entangled, then always mark it as in-use because we can't determine reachability across threads. - if (!(*iter)->locallyEntangledPort() || (*iter)->hasPendingActivity()) { - DOMObject* wrapper = getCachedDOMObjectWrapper(globalData, *iter); - if (wrapper) - markStack.append(wrapper); + if (!(*iter)->locallyEntangledPort() || (*iter)->hasPendingActivity()) + markDOMObjectWrapper(markStack, globalData, *iter); + } +} + +typedef std::pair<JSNode*, DOMWrapperWorld*> WrapperAndWorld; +typedef WTF::Vector<WrapperAndWorld, 8> WrapperSet; + +static inline void takeWrappers(Node* node, Document* document, WrapperSet& wrapperSet) +{ + if (document) { + JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap(); + for (JSWrapperCacheMap::iterator iter = wrapperCacheMap.begin(); iter != wrapperCacheMap.end(); ++iter) { + if (JSNode* wrapper = iter->second->take(node)) { + removeWrapper(wrapper); + wrapperSet.append(WrapperAndWorld(wrapper, iter->first)); + } + } + } else { + for (JSGlobalDataWorldIterator worldIter(JSDOMWindow::commonJSGlobalData()); worldIter; ++worldIter) { + DOMWrapperWorld* world = *worldIter; + if (JSNode* wrapper = static_cast<JSNode*>(world->m_wrappers.take(node))) { + removeWrapper(wrapper); + wrapperSet.append(WrapperAndWorld(wrapper, world)); + } } } } @@ -377,13 +509,18 @@ void markActiveObjectsForContext(MarkStack& markStack, JSGlobalData& globalData, void updateDOMNodeDocument(Node* node, Document* oldDocument, Document* newDocument) { ASSERT(oldDocument != newDocument); - JSNode* wrapper = getCachedDOMNodeWrapper(oldDocument, node); - if (!wrapper) - return; - removeWrapper(wrapper); - cacheDOMNodeWrapper(newDocument, node, wrapper); - forgetDOMNode(oldDocument, node); - addWrapper(wrapper); + + WrapperSet wrapperSet; + takeWrappers(node, oldDocument, wrapperSet); + + for (unsigned i = 0; i < wrapperSet.size(); ++i) { + JSNode* wrapper = wrapperSet[i].first; + if (newDocument) + newDocument->getWrapperCache(wrapperSet[i].second)->set(node, wrapper); + else + wrapperSet[i].second->m_wrappers.set(node, wrapper); + addWrapper(wrapper); + } } void markDOMObjectWrapper(MarkStack& markStack, JSGlobalData& globalData, void* object) @@ -393,10 +530,11 @@ void markDOMObjectWrapper(MarkStack& markStack, JSGlobalData& globalData, void* // but doing this correctly would be challenging. if (!object) return; - DOMObject* wrapper = getCachedDOMObjectWrapper(globalData, object); - if (!wrapper) - return; - markStack.append(wrapper); + + for (JSGlobalDataWorldIterator worldIter(&globalData); worldIter; ++worldIter) { + if (DOMObject* wrapper = worldIter->m_wrappers.get(object)) + markStack.append(wrapper); + } } JSValue jsStringOrNull(ExecState* exec, const String& s) @@ -543,7 +681,7 @@ bool allowsAccessFromFrame(ExecState* exec, Frame* frame) { if (!frame) return false; - JSDOMWindow* window = toJSDOMWindow(frame); + JSDOMWindow* window = toJSDOMWindow(frame, currentWorld(exec)); return window && window->allowsAccessFrom(exec); } @@ -551,7 +689,7 @@ bool allowsAccessFromFrame(ExecState* exec, Frame* frame, String& message) { if (!frame) return false; - JSDOMWindow* window = toJSDOMWindow(frame); + JSDOMWindow* window = toJSDOMWindow(frame, currentWorld(exec)); return window && window->allowsAccessFrom(exec, message); } @@ -565,8 +703,16 @@ void printErrorMessageForFrame(Frame* frame, const String& message) { if (!frame) return; - if (JSDOMWindow* window = toJSDOMWindow(frame)) - window->printErrorMessage(message); + if (message.isEmpty()) + return; + + Settings* settings = frame->settings(); + if (!settings) + return; + if (settings->privateBrowsingEnabled()) + return; + + frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, message, 1, String()); // FIXME: provide a real line number and source URL. } Frame* toLexicalFrame(ExecState* exec) @@ -664,4 +810,28 @@ bool DOMObject::defineOwnProperty(ExecState* exec, const Identifier&, PropertyDe return false; } +JSValue DebuggerCallFrame_evaluateInWorld(const JSC::DebuggerCallFrame& debuggerCallFrame, const UString& script, JSValue& exception) +{ + EnterDOMWrapperWorld worldEntry(debuggerCallFrame.dynamicGlobalObject()->globalExec(), debuggerWorld()); + return debuggerCallFrame.evaluate(script, exception); +} + +JSValue callInWorld(ExecState* exec, JSValue function, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args, DOMWrapperWorld* isolatedWorld) +{ + EnterDOMWrapperWorld worldEntry(exec, isolatedWorld); + return JSC::call(exec, function, callType, callData, thisValue, args); +} + +JSObject* constructInWorld(ExecState* exec, JSValue object, ConstructType constructType, const ConstructData& constructData, const ArgList& args, DOMWrapperWorld* isolatedWorld) +{ + EnterDOMWrapperWorld worldEntry(exec, isolatedWorld); + return JSC::construct(exec, object, constructType, constructData, args); +} + +Completion evaluateInWorld(ExecState* exec, ScopeChain& scopeChain, const SourceCode& sourceCode, JSValue thisValue, DOMWrapperWorld* isolatedWorld) +{ + EnterDOMWrapperWorld worldEntry(exec, isolatedWorld); + return JSC::evaluate(exec, scopeChain, sourceCode, thisValue); +} + } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMBinding.h b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMBinding.h index 9af45d7..ba41d85 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMBinding.h +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMBinding.h @@ -30,16 +30,18 @@ namespace JSC { class JSGlobalData; + class DebuggerCallFrame; } namespace WebCore { class Document; class Frame; + class JSNode; class KURL; class Node; class String; - class JSNode; + class ScriptController; typedef int ExceptionCode; @@ -136,14 +138,104 @@ namespace WebCore { } }; + typedef HashMap<void*, DOMObject*> DOMObjectWrapperMap; + + class DOMWrapperWorld : public RefCounted<DOMWrapperWorld> { + public: + DOMWrapperWorld(JSC::JSGlobalData*); + ~DOMWrapperWorld(); + + void rememberDocument(Document* document) { documentsWithWrappers.add(document); } + void forgetDocument(Document* document) { documentsWithWrappers.remove(document); } + void rememberScriptController(ScriptController* scriptController) { scriptControllersWithShells.add(scriptController); } + void forgetScriptController(ScriptController* scriptController) { scriptControllersWithShells.remove(scriptController); } + + // FIXME: can we make this private? + DOMObjectWrapperMap m_wrappers; + + private: + JSC::JSGlobalData* m_globalData; + HashSet<Document*> documentsWithWrappers; + HashSet<ScriptController*> scriptControllersWithShells; + }; + + // Map from static HashTable instances to per-GlobalData ones. + class DOMObjectHashTableMap { + public: + static DOMObjectHashTableMap& mapFor(JSC::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 JSC::JSGlobalData::ClientData { + friend class EnterDOMWrapperWorld; + friend class JSGlobalDataWorldIterator; + + public: + WebCoreJSClientData(JSC::JSGlobalData* globalData) + : m_normalWorld(globalData) + { + m_worldStack.append(&m_normalWorld); + m_worldSet.add(&m_normalWorld); + } + // FIXME: add a destructor to assert m_worldSet only contains m_normalWorld? + + DOMWrapperWorld* currentWorld() { return m_worldStack.last(); } + DOMWrapperWorld* normalWorld() { return &m_normalWorld; } + + void rememberWorld(DOMWrapperWorld* world) + { + ASSERT(!m_worldSet.contains(world)); + m_worldSet.add(world); + } + void forgetWorld(DOMWrapperWorld* world) + { + ASSERT(m_worldSet.contains(world)); + m_worldSet.remove(world); + } + + DOMObjectHashTableMap hashTableMap; + private: + Vector<DOMWrapperWorld*> m_worldStack; + HashSet<DOMWrapperWorld*> m_worldSet; + DOMWrapperWorld m_normalWorld; + }; + + class EnterDOMWrapperWorld { + public: + EnterDOMWrapperWorld(JSC::JSGlobalData&, DOMWrapperWorld*); + EnterDOMWrapperWorld(JSC::ExecState*, DOMWrapperWorld*); + ~EnterDOMWrapperWorld(); + + private: + WebCoreJSClientData* m_clientData; + }; + DOMObject* getCachedDOMObjectWrapper(JSC::JSGlobalData&, void* objectHandle); void cacheDOMObjectWrapper(JSC::JSGlobalData&, void* objectHandle, DOMObject* wrapper); - void forgetDOMObject(JSC::JSGlobalData&, void* objectHandle); + void forgetDOMNode(DOMObject* wrapper, Node* node, Document* document); + void forgetDOMObject(DOMObject* wrapper, void* objectHandle); JSNode* getCachedDOMNodeWrapper(Document*, Node*); void cacheDOMNodeWrapper(Document*, Node*, JSNode* wrapper); - void forgetDOMNode(Document*, Node*); void forgetAllDOMNodesForDocument(Document*); + void forgetWorldOfDOMNodesForDocument(Document*, DOMWrapperWorld*); void updateDOMNodeDocument(Node*, Document* oldDocument, Document* newDocument); void markDOMNodesForDocument(JSC::MarkStack&, Document*); void markActiveObjectsForContext(JSC::MarkStack&, JSC::JSGlobalData&, ScriptExecutionContext*); @@ -154,6 +246,13 @@ namespace WebCore { JSC::Structure* getCachedDOMStructure(JSC::ExecState*, const JSC::ClassInfo*); JSC::Structure* cacheDOMStructure(JSC::ExecState*, NonNullPassRefPtr<JSC::Structure>, const JSC::ClassInfo*); + DOMWrapperWorld* currentWorld(JSC::ExecState*); + DOMWrapperWorld* normalWorld(JSC::JSGlobalData&); + DOMWrapperWorld* mainThreadCurrentWorld(); + DOMWrapperWorld* mainThreadNormalWorld(); + inline DOMWrapperWorld* debuggerWorld() { return mainThreadNormalWorld(); } + inline DOMWrapperWorld* pluginWorld() { return mainThreadNormalWorld(); } + JSC::JSObject* getCachedDOMConstructor(JSC::ExecState*, const JSC::ClassInfo*); void cacheDOMConstructor(JSC::ExecState*, const JSC::ClassInfo*, JSC::JSObject* constructor); @@ -305,6 +404,11 @@ namespace WebCore { bool processingUserGesture(JSC::ExecState*); KURL completeURL(JSC::ExecState*, const String& relativeURL); + JSC::JSValue DebuggerCallFrame_evaluateInWorld(const JSC::DebuggerCallFrame& debuggerCallFrame, const JSC::UString& script, JSC::JSValue& exception); + JSC::JSValue callInWorld(JSC::ExecState*, JSC::JSValue function, JSC::CallType, const JSC::CallData&, JSC::JSValue thisValue, const JSC::ArgList&, DOMWrapperWorld*); + JSC::JSObject* constructInWorld(JSC::ExecState* exec, JSC::JSValue object, JSC::ConstructType constructType, const JSC::ConstructData& constructData, const JSC::ArgList& args, DOMWrapperWorld*); + JSC::Completion evaluateInWorld(JSC::ExecState*, JSC::ScopeChain&, const JSC::SourceCode&, JSC::JSValue thisValue, DOMWrapperWorld*); + } // namespace WebCore #endif // JSDOMBinding_h diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMGlobalObject.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMGlobalObject.cpp index 53bb26b..011a4e4 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMGlobalObject.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMGlobalObject.cpp @@ -63,7 +63,7 @@ PassRefPtr<JSEventListener> JSDOMGlobalObject::createJSAttributeEventListener(JS if (!val.isObject()) return 0; - return JSEventListener::create(asObject(val), true).get(); + return JSEventListener::create(asObject(val), true, currentWorld(globalExec())).get(); } void JSDOMGlobalObject::setCurrentEvent(Event* evt) @@ -81,15 +81,34 @@ void JSDOMGlobalObject::destroyJSDOMGlobalObjectData(void* jsDOMGlobalObjectData delete static_cast<JSDOMGlobalObjectData*>(jsDOMGlobalObjectData); } -JSDOMGlobalObject* toJSDOMGlobalObject(Document* document) +JSDOMGlobalObject* toJSDOMGlobalObject(Document* document, JSC::ExecState* exec) { - return toJSDOMWindow(document->frame()); + return toJSDOMWindow(document->frame(), currentWorld(exec)); } -JSDOMGlobalObject* toJSDOMGlobalObject(ScriptExecutionContext* scriptExecutionContext) +JSDOMGlobalObject* toJSDOMGlobalObject(ScriptExecutionContext* scriptExecutionContext, JSC::ExecState* exec) { if (scriptExecutionContext->isDocument()) - return toJSDOMGlobalObject(static_cast<Document*>(scriptExecutionContext)); + return toJSDOMGlobalObject(static_cast<Document*>(scriptExecutionContext), exec); + +#if ENABLE(WORKERS) + if (scriptExecutionContext->isWorkerContext()) + return static_cast<WorkerContext*>(scriptExecutionContext)->script()->workerContextWrapper(); +#endif + + ASSERT_NOT_REACHED(); + return 0; +} + +JSDOMGlobalObject* toJSDOMGlobalObject(Document* document, DOMWrapperWorld* world) +{ + return toJSDOMWindow(document->frame(), world); +} + +JSDOMGlobalObject* toJSDOMGlobalObject(ScriptExecutionContext* scriptExecutionContext, DOMWrapperWorld* world) +{ + if (scriptExecutionContext->isDocument()) + return toJSDOMGlobalObject(static_cast<Document*>(scriptExecutionContext), world); #if ENABLE(WORKERS) if (scriptExecutionContext->isWorkerContext()) diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMGlobalObject.h b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMGlobalObject.h index ce26857..6b75a6f 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMGlobalObject.h +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMGlobalObject.h @@ -33,6 +33,7 @@ namespace WebCore { class Document; class Event; + class DOMWrapperWorld; class JSLazyEventListener; class JSEventListener; class ScriptExecutionContext; @@ -102,8 +103,11 @@ namespace WebCore { return constructor; } - JSDOMGlobalObject* toJSDOMGlobalObject(Document*); - JSDOMGlobalObject* toJSDOMGlobalObject(ScriptExecutionContext*); + JSDOMGlobalObject* toJSDOMGlobalObject(Document*, JSC::ExecState*); + JSDOMGlobalObject* toJSDOMGlobalObject(ScriptExecutionContext*, JSC::ExecState*); + + JSDOMGlobalObject* toJSDOMGlobalObject(Document*, DOMWrapperWorld*); + JSDOMGlobalObject* toJSDOMGlobalObject(ScriptExecutionContext*, DOMWrapperWorld*); } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowBase.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowBase.cpp index a04ef89..86ff149 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowBase.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowBase.cpp @@ -53,10 +53,11 @@ JSDOMWindowBase::JSDOMWindowBase(NonNullPassRefPtr<Structure> structure, PassRef addStaticGlobals(staticGlobals, sizeof(staticGlobals) / sizeof(GlobalPropertyInfo)); } -void JSDOMWindowBase::updateDocument() +void JSDOMWindowBase::updateDocument(DOMWrapperWorld* world) { ASSERT(d()->impl->document()); ExecState* exec = globalExec(); + EnterDOMWrapperWorld worldEntry(exec, world); symbolTablePutWithAttributes(Identifier(exec, "document"), toJS(exec, this, d()->impl->document()), DontDelete | ReadOnly); } @@ -79,21 +80,7 @@ String JSDOMWindowBase::crossDomainAccessErrorMessage(const JSGlobalObject* othe void JSDOMWindowBase::printErrorMessage(const String& message) const { - if (message.isEmpty()) - return; - - Frame* frame = impl()->frame(); - if (!frame) - return; - - Settings* settings = frame->settings(); - if (!settings) - return; - - if (settings->privateBrowsingEnabled()) - return; - - impl()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, message, 1, String()); // FIXME: provide a real line number and source URL. + printErrorMessageForFrame(impl()->frame(), message); } ExecState* JSDOMWindowBase::globalExec() @@ -157,13 +144,16 @@ JSDOMWindowShell* JSDOMWindowBase::shell() const JSGlobalData* JSDOMWindowBase::commonJSGlobalData() { - static JSGlobalData* globalData; + ASSERT(isMainThread()); + + static JSGlobalData* globalData = 0; if (!globalData) { globalData = JSGlobalData::createLeaked().releaseRef(); globalData->timeoutChecker.setTimeoutInterval(10000); // 10 seconds #ifndef NDEBUG globalData->mainThreadOnly = true; #endif + globalData->clientData = new WebCoreJSClientData(globalData); } return globalData; @@ -181,21 +171,21 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject*, DOMWindow* domWindow) return toJS(exec, domWindow); } -JSValue toJS(ExecState*, DOMWindow* domWindow) +JSValue toJS(ExecState* exec, DOMWindow* domWindow) { if (!domWindow) return jsNull(); Frame* frame = domWindow->frame(); if (!frame) return jsNull(); - return frame->script()->windowShell(); + return frame->script()->windowShell(currentWorld(exec)); } -JSDOMWindow* toJSDOMWindow(Frame* frame) +JSDOMWindow* toJSDOMWindow(Frame* frame, DOMWrapperWorld* world) { if (!frame) return 0; - return frame->script()->windowShell()->window(); + return frame->script()->windowShell(world)->window(); } JSDOMWindow* toJSDOMWindow(JSValue value) diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowBase.h b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowBase.h index 52c3c1d..31e2486 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowBase.h +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowBase.h @@ -32,6 +32,7 @@ namespace WebCore { class DOMWindow; class Event; class Frame; + class DOMWrapperWorld; class JSDOMWindow; class JSDOMWindowShell; class JSLocation; @@ -46,7 +47,7 @@ namespace WebCore { JSDOMWindowBase(NonNullPassRefPtr<JSC::Structure>, PassRefPtr<DOMWindow>, JSDOMWindowShell*); public: - void updateDocument(); + void updateDocument(DOMWrapperWorld*); DOMWindow* impl() const { return d()->impl.get(); } virtual ScriptExecutionContext* scriptExecutionContext() const; @@ -102,7 +103,7 @@ namespace WebCore { JSC::JSValue toJS(JSC::ExecState*, DOMWindow*); // Returns JSDOMWindow or 0 - JSDOMWindow* toJSDOMWindow(Frame*); + JSDOMWindow* toJSDOMWindow(Frame*, DOMWrapperWorld*); JSDOMWindow* toJSDOMWindow(JSC::JSValue); } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowCustom.cpp index deb92cb..2804b3c 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowCustom.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowCustom.cpp @@ -771,7 +771,8 @@ static Frame* createWindow(ExecState* exec, Frame* lexicalFrame, Frame* dynamicF newFrame->loader()->setOpener(openerFrame); newFrame->page()->setOpenedByDOM(); - JSDOMWindow* newWindow = toJSDOMWindow(newFrame); + // FIXME: If a window is created from an isolated world, what are the consequences of this? 'dialogArguments' only appears back in the normal world? + JSDOMWindow* newWindow = toJSDOMWindow(newFrame, normalWorld(exec->globalData())); if (dialogArgs) newWindow->putDirect(Identifier(exec, "dialogArguments"), dialogArgs); @@ -831,7 +832,7 @@ JSValue JSDOMWindow::open(ExecState* exec, const ArgList& args) if (!shouldAllowNavigation(exec, frame)) return jsUndefined(); - const JSDOMWindow* targetedWindow = toJSDOMWindow(frame); + const JSDOMWindow* targetedWindow = toJSDOMWindow(frame, currentWorld(exec)); if (!completedURL.isEmpty() && (!protocolIsJavaScript(completedURL) || (targetedWindow && targetedWindow->allowsAccessFrom(exec)))) { bool userGesture = processingUserGesture(exec); @@ -932,7 +933,7 @@ JSValue JSDOMWindow::showModalDialog(ExecState* exec, const ArgList& args) if (!dialogFrame) return jsUndefined(); - JSDOMWindow* dialogWindow = toJSDOMWindow(dialogFrame); + JSDOMWindow* dialogWindow = toJSDOMWindow(dialogFrame, currentWorld(exec)); dialogFrame->page()->chrome()->runModal(); Identifier returnValue(exec, "returnValue"); @@ -975,7 +976,7 @@ JSValue JSDOMWindow::postMessage(ExecState* exec, const ArgList& args) JSValue JSDOMWindow::setTimeout(ExecState* exec, const ArgList& args) { - ScheduledAction* action = ScheduledAction::create(exec, args); + ScheduledAction* action = ScheduledAction::create(exec, args, currentWorld(exec)); if (exec->hadException()) return jsUndefined(); int delay = args.at(1).toInt32(exec); @@ -984,7 +985,7 @@ JSValue JSDOMWindow::setTimeout(ExecState* exec, const ArgList& args) JSValue JSDOMWindow::setInterval(ExecState* exec, const ArgList& args) { - ScheduledAction* action = ScheduledAction::create(exec, args); + ScheduledAction* action = ScheduledAction::create(exec, args, currentWorld(exec)); if (exec->hadException()) return jsUndefined(); int delay = args.at(1).toInt32(exec); @@ -1052,7 +1053,7 @@ JSValue JSDOMWindow::addEventListener(ExecState* exec, const ArgList& args) if (!listener.isObject()) return jsUndefined(); - impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false), args.at(2).toBoolean(exec)); + impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)), args.at(2).toBoolean(exec)); return jsUndefined(); } @@ -1066,7 +1067,7 @@ JSValue JSDOMWindow::removeEventListener(ExecState* exec, const ArgList& args) if (!listener.isObject()) return jsUndefined(); - impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec)); + impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); return jsUndefined(); } diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowShell.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowShell.cpp index 3c3ff4c..9072f91 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowShell.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowShell.cpp @@ -171,18 +171,18 @@ void* JSDOMWindowShell::operator new(size_t size) // Conversion methods // ---- -JSValue toJS(ExecState*, Frame* frame) +JSValue toJS(ExecState* exec, Frame* frame) { if (!frame) return jsNull(); - return frame->script()->windowShell(); + return frame->script()->windowShell(currentWorld(exec)); } -JSDOMWindowShell* toJSDOMWindowShell(Frame* frame) +JSDOMWindowShell* toJSDOMWindowShell(Frame* frame, DOMWrapperWorld* isolatedWorld) { if (!frame) return 0; - return frame->script()->windowShell(); + return frame->script()->windowShell(isolatedWorld); } } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowShell.h b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowShell.h index 1bb0938..36cb8d6 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowShell.h +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowShell.h @@ -88,7 +88,7 @@ namespace WebCore { }; JSC::JSValue toJS(JSC::ExecState*, Frame*); - JSDOMWindowShell* toJSDOMWindowShell(Frame*); + JSDOMWindowShell* toJSDOMWindowShell(Frame*, DOMWrapperWorld*); } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSDesktopNotificationsCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSDesktopNotificationsCustom.cpp index 9bff637..7485c1f 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSDesktopNotificationsCustom.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSDesktopNotificationsCustom.cpp @@ -67,7 +67,7 @@ JSValue JSNotification::addEventListener(ExecState* exec, const ArgList& args) if (!listener.isObject()) return jsUndefined(); - impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener)), false), args.at(2).toBoolean(exec)); + impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener)), false, currentWorld(exec)), args.at(2).toBoolean(exec)); return jsUndefined(); } @@ -77,7 +77,7 @@ JSValue JSNotification::removeEventListener(ExecState* exec, const ArgList& args if (!listener.isObject()) return jsUndefined(); - impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec)); + impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); return jsUndefined(); } diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSEventListener.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSEventListener.cpp index 4f273fe..1a999a8 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSEventListener.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSEventListener.cpp @@ -31,10 +31,11 @@ using namespace JSC; namespace WebCore { -JSEventListener::JSEventListener(JSObject* function, bool isAttribute) +JSEventListener::JSEventListener(JSObject* function, bool isAttribute, DOMWrapperWorld* isolatedWorld) : EventListener(JSEventListenerType) , m_jsFunction(function) , m_isAttribute(isAttribute) + , m_isolatedWorld(isolatedWorld) { } @@ -65,7 +66,7 @@ void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext if (!jsFunction) return; - JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(scriptExecutionContext); + JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(scriptExecutionContext, m_isolatedWorld.get()); if (!globalObject) return; @@ -86,7 +87,12 @@ void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext ExecState* exec = globalObject->globalExec(); - JSValue handleEventFunction = jsFunction->get(exec, Identifier(exec, "handleEvent")); + JSValue handleEventFunction; + { + // Switch worlds, just in case handleEvent is a getter and causes JS execution! + EnterDOMWrapperWorld worldEntry(exec, m_isolatedWorld.get()); + handleEventFunction = jsFunction->get(exec, Identifier(exec, "handleEvent")); + } CallData callData; CallType callType = handleEventFunction.getCallData(callData); if (callType == CallTypeNone) { @@ -108,8 +114,8 @@ void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext globalData->timeoutChecker.start(); JSValue retval = handleEventFunction - ? call(exec, handleEventFunction, callType, callData, jsFunction, args) - : call(exec, jsFunction, callType, callData, toJS(exec, globalObject, event->currentTarget()), args); + ? callInWorld(exec, handleEventFunction, callType, callData, jsFunction, args, m_isolatedWorld.get()) + : callInWorld(exec, jsFunction, callType, callData, toJS(exec, globalObject, event->currentTarget()), args, m_isolatedWorld.get()); globalData->timeoutChecker.stop(); globalObject->setCurrentEvent(savedEvent); @@ -140,7 +146,7 @@ bool JSEventListener::reportError(ScriptExecutionContext* context, const String& if (!jsFunction) return false; - JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(context); + JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(context, m_isolatedWorld.get()); ExecState* exec = globalObject->globalExec(); CallData callData; @@ -160,7 +166,7 @@ bool JSEventListener::reportError(ScriptExecutionContext* context, const String& JSValue thisValue = globalObject->toThisObject(exec); globalData->timeoutChecker.start(); - JSValue returnValue = call(exec, jsFunction, callType, callData, thisValue, args); + JSValue returnValue = callInWorld(exec, jsFunction, callType, callData, thisValue, args, m_isolatedWorld.get()); globalData->timeoutChecker.stop(); // If an error occurs while handling the script error, it should be bubbled up. diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSEventListener.h b/src/3rdparty/webkit/WebCore/bindings/js/JSEventListener.h index 285a9c4..bf3af48 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSEventListener.h +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSEventListener.h @@ -30,9 +30,9 @@ namespace WebCore { class JSEventListener : public EventListener { public: - static PassRefPtr<JSEventListener> create(JSC::JSObject* listener, bool isAttribute) + static PassRefPtr<JSEventListener> create(JSC::JSObject* listener, bool isAttribute, DOMWrapperWorld* isolatedWorld) { - return adoptRef(new JSEventListener(listener, isAttribute)); + return adoptRef(new JSEventListener(listener, isAttribute, isolatedWorld)); } static const JSEventListener* cast(const EventListener* listener) @@ -59,10 +59,11 @@ namespace WebCore { void clearJSFunctionInline(); protected: - JSEventListener(JSC::JSObject* function, bool isAttribute); + JSEventListener(JSC::JSObject* function, bool isAttribute, DOMWrapperWorld* isolatedWorld); mutable JSC::JSObject* m_jsFunction; bool m_isAttribute; + RefPtr<DOMWrapperWorld> m_isolatedWorld; }; } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSEventSourceCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSEventSourceCustom.cpp index 00dfe12..8f0dfb1 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSEventSourceCustom.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSEventSourceCustom.cpp @@ -49,7 +49,7 @@ JSValue JSEventSource::addEventListener(ExecState* exec, const ArgList& args) if (!listener.isObject()) return jsUndefined(); - impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec)); + impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); return jsUndefined(); } @@ -59,7 +59,7 @@ JSValue JSEventSource::removeEventListener(ExecState* exec, const ArgList& args) if (!listener.isObject()) return jsUndefined(); - impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec)); + impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); return jsUndefined(); } diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSEventTarget.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSEventTarget.cpp index 0421d10..6ea1135 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSEventTarget.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSEventTarget.cpp @@ -128,7 +128,7 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, EventTarget* targ return toJS(exec, globalObject, worker); if (DedicatedWorkerContext* workerContext = target->toDedicatedWorkerContext()) - return toJSDOMGlobalObject(workerContext); + return toJSDOMGlobalObject(workerContext, exec); #endif #if ENABLE(SHARED_WORKERS) @@ -136,7 +136,7 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, EventTarget* targ return toJS(exec, globalObject, sharedWorker); if (SharedWorkerContext* workerContext = target->toSharedWorkerContext()) - return toJSDOMGlobalObject(workerContext); + return toJSDOMGlobalObject(workerContext, exec); #endif #if ENABLE(NOTIFICATIONS) diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSHTMLAllCollection.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSHTMLAllCollection.cpp deleted file mode 100644 index ce2609c..0000000 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSHTMLAllCollection.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2008 Apple 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: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 "JSHTMLAllCollection.h" - -using namespace JSC; - -namespace WebCore { - -const ClassInfo JSHTMLAllCollection::s_info = { "HTMLAllCollection", 0, 0, 0 }; - -} // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSHTMLAllCollection.h b/src/3rdparty/webkit/WebCore/bindings/js/JSHTMLAllCollection.h deleted file mode 100644 index da3a758..0000000 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSHTMLAllCollection.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2007, 2008 Apple 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: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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. - */ - -#ifndef JSHTMLAllCollection_h -#define JSHTMLAllCollection_h - -#include "HTMLCollection.h" -#include "JSHTMLCollection.h" - -namespace WebCore { - - class HTMLCollection; - - class JSHTMLAllCollection : public JSHTMLCollection { - public: - JSHTMLAllCollection(NonNullPassRefPtr<JSC::Structure> structure, JSDOMGlobalObject* globalObject, PassRefPtr<HTMLCollection> collection) - : JSHTMLCollection(structure, globalObject, collection) - { - } - - static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue proto) - { - return JSC::Structure::create(proto, JSC::TypeInfo(JSC::ObjectType, StructureFlags)); - } - - static const JSC::ClassInfo s_info; - protected: - static const unsigned StructureFlags = JSC::OverridesGetOwnPropertySlot | JSC::MasqueradesAsUndefined | JSC::OverridesMarkChildren | JSC::OverridesGetPropertyNames | JSHTMLCollection::StructureFlags; - - private: - virtual bool toBoolean(JSC::ExecState*) const { return false; } - }; - -} // namespace WebCore - -#endif // JSHTMLAllCollection_h diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSHTMLAllCollectionCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSHTMLAllCollectionCustom.cpp new file mode 100644 index 0000000..fd1dd11 --- /dev/null +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSHTMLAllCollectionCustom.cpp @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2009 Apple 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: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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 "JSHTMLAllCollection.h" + +#include "AtomicString.h" +#include "HTMLAllCollection.h" +#include "JSDOMBinding.h" +#include "JSHTMLAllCollection.h" +#include "JSNode.h" +#include "JSNodeList.h" +#include "Node.h" +#include "StaticNodeList.h" +#include <wtf/Vector.h> + +using namespace JSC; + +namespace WebCore { + +static JSValue getNamedItems(ExecState* exec, JSHTMLAllCollection* collection, const Identifier& propertyName) +{ + Vector<RefPtr<Node> > namedItems; + collection->impl()->namedItems(propertyName, namedItems); + + if (namedItems.isEmpty()) + return jsUndefined(); + if (namedItems.size() == 1) + return toJS(exec, collection->globalObject(), namedItems[0].get()); + + // FIXME: HTML5 specifies that this should be a DynamicNodeList. + // FIXME: HTML5 specifies that non-HTMLOptionsCollection collections should return + // the first matching item instead of a NodeList. + return toJS(exec, collection->globalObject(), StaticNodeList::adopt(namedItems).get()); +} + +// HTMLCollections are strange objects, they support both get and call, +// so that document.forms.item(0) and document.forms(0) both work. +static JSValue JSC_HOST_CALL callHTMLAllCollection(ExecState* exec, JSObject* function, JSValue, const ArgList& args) +{ + if (args.size() < 1) + return jsUndefined(); + + // Do not use thisObj here. It can be the JSHTMLDocument, in the document.forms(i) case. + JSHTMLAllCollection* jsCollection = static_cast<JSHTMLAllCollection*>(function); + HTMLAllCollection* collection = static_cast<HTMLAllCollection*>(jsCollection->impl()); + + // Also, do we need the TypeError test here ? + + if (args.size() == 1) { + // Support for document.all(<index>) etc. + bool ok; + UString string = args.at(0).toString(exec); + unsigned index = string.toUInt32(&ok, false); + if (ok) + return toJS(exec, jsCollection->globalObject(), collection->item(index)); + + // Support for document.images('<name>') etc. + return getNamedItems(exec, jsCollection, Identifier(exec, string)); + } + + // The second arg, if set, is the index of the item we want + bool ok; + UString string = args.at(0).toString(exec); + unsigned index = args.at(1).toString(exec).toUInt32(&ok, false); + if (ok) { + String pstr = string; + Node* node = collection->namedItem(pstr); + while (node) { + if (!index) + return toJS(exec, jsCollection->globalObject(), node); + node = collection->nextNamedItem(pstr); + --index; + } + } + + return jsUndefined(); +} + +CallType JSHTMLAllCollection::getCallData(CallData& callData) +{ + callData.native.function = callHTMLAllCollection; + return CallTypeHost; +} + +bool JSHTMLAllCollection::canGetItemsForName(ExecState*, HTMLAllCollection* collection, const Identifier& propertyName) +{ + Vector<RefPtr<Node> > namedItems; + collection->namedItems(propertyName, namedItems); + return !namedItems.isEmpty(); +} + +JSValue JSHTMLAllCollection::nameGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) +{ + JSHTMLAllCollection* thisObj = static_cast<JSHTMLAllCollection*>(asObject(slot.slotBase())); + return getNamedItems(exec, thisObj, propertyName); +} + +JSValue JSHTMLAllCollection::item(ExecState* exec, const ArgList& args) +{ + bool ok; + uint32_t index = args.at(0).toString(exec).toUInt32(&ok, false); + if (ok) + return toJS(exec, globalObject(), impl()->item(index)); + return getNamedItems(exec, this, Identifier(exec, args.at(0).toString(exec))); +} + +JSValue JSHTMLAllCollection::namedItem(ExecState* exec, const ArgList& args) +{ + return getNamedItems(exec, this, Identifier(exec, args.at(0).toString(exec))); +} + +} // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSHTMLCollectionCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSHTMLCollectionCustom.cpp index 8ffddf7..dd4ceaa 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSHTMLCollectionCustom.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSHTMLCollectionCustom.cpp @@ -23,6 +23,7 @@ #include "AtomicString.h" #include "HTMLCollection.h" #include "HTMLOptionsCollection.h" +#include "HTMLAllCollection.h" #include "JSDOMBinding.h" #include "JSHTMLAllCollection.h" #include "JSHTMLOptionsCollection.h" @@ -143,7 +144,6 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, HTMLCollection* c wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, HTMLOptionsCollection, collection); break; case DocAll: - typedef HTMLCollection HTMLAllCollection; wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, HTMLAllCollection, collection); break; default: diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSHTMLDocumentCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSHTMLDocumentCustom.cpp index c113ec7..a65ca7c 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSHTMLDocumentCustom.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSHTMLDocumentCustom.cpp @@ -28,6 +28,7 @@ #include "CharacterNames.h" #include "Frame.h" +#include "HTMLAllCollection.h" #include "HTMLBodyElement.h" #include "HTMLCollection.h" #include "HTMLDocument.h" @@ -105,14 +106,14 @@ JSValue JSHTMLDocument::open(ExecState* exec, const ArgList& args) if (args.size() > 2) { Frame* frame = static_cast<HTMLDocument*>(impl())->frame(); if (frame) { - JSDOMWindowShell* wrapper = toJSDOMWindowShell(frame); + JSDOMWindowShell* wrapper = toJSDOMWindowShell(frame, currentWorld(exec)); if (wrapper) { JSValue function = wrapper->get(exec, Identifier(exec, "open")); CallData callData; CallType callType = function.getCallData(callData); if (callType == CallTypeNone) return throwError(exec, TypeError); - return call(exec, function, callType, callData, wrapper, args); + return callInWorld(exec, function, callType, callData, wrapper, args, currentWorld(exec)); } } return jsUndefined(); diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSHTMLFrameSetElementCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSHTMLFrameSetElementCustom.cpp index 05972e6..68769d6 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSHTMLFrameSetElementCustom.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSHTMLFrameSetElementCustom.cpp @@ -47,14 +47,14 @@ bool JSHTMLFrameSetElement::canGetItemsForName(ExecState*, HTMLFrameSetElement* return frame && frame->hasTagName(frameTag); } -JSValue JSHTMLFrameSetElement::nameGetter(ExecState*, const Identifier& propertyName, const PropertySlot& slot) +JSValue JSHTMLFrameSetElement::nameGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) { JSHTMLElement* thisObj = static_cast<JSHTMLElement*>(asObject(slot.slotBase())); HTMLElement* element = static_cast<HTMLElement*>(thisObj->impl()); Node* frame = element->children()->namedItem(propertyName); if (Document* doc = static_cast<HTMLFrameElement*>(frame)->contentDocument()) { - if (JSDOMWindowShell* window = toJSDOMWindowShell(doc->frame())) + if (JSDOMWindowShell* window = toJSDOMWindowShell(doc->frame(), currentWorld(exec))) return window; } diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSInspectorBackendCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSInspectorBackendCustom.cpp index 391cacc..439f532 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSInspectorBackendCustom.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSInspectorBackendCustom.cpp @@ -131,7 +131,8 @@ JSValue JSInspectorBackend::databaseForId(ExecState* exec, const ArgList& args) Database* database = impl()->databaseForId(args.at(0).toInt32(exec)); if (!database) return jsUndefined(); - JSDOMWindow* inspectedWindow = toJSDOMWindow(ic->inspectedPage()->mainFrame()); + // Could use currentWorld(exec) ... but which exec! The following mixed use of exec & inspectedWindow->globalExec() scares me! + JSDOMWindow* inspectedWindow = toJSDOMWindow(ic->inspectedPage()->mainFrame(), debuggerWorld()); return JSInspectedObjectWrapper::wrap(inspectedWindow->globalExec(), toJS(exec, database)); } #endif @@ -141,7 +142,7 @@ JSValue JSInspectorBackend::inspectedWindow(ExecState*, const ArgList&) InspectorController* ic = impl()->inspectorController(); if (!ic) return jsUndefined(); - JSDOMWindow* inspectedWindow = toJSDOMWindow(ic->inspectedPage()->mainFrame()); + JSDOMWindow* inspectedWindow = toJSDOMWindow(ic->inspectedPage()->mainFrame(), debuggerWorld()); return JSInspectedObjectWrapper::wrap(inspectedWindow->globalExec(), inspectedWindow); } @@ -266,7 +267,7 @@ JSValue JSInspectorBackend::nodeForId(ExecState* exec, const ArgList& args) return jsUndefined(); JSLock lock(SilenceAssertionsOnly); - JSDOMWindow* inspectedWindow = toJSDOMWindow(ic->inspectedPage()->mainFrame()); + JSDOMWindow* inspectedWindow = toJSDOMWindow(ic->inspectedPage()->mainFrame(), debuggerWorld()); return JSInspectedObjectWrapper::wrap(inspectedWindow->globalExec(), toJS(exec, deprecatedGlobalObjectForPrototype(inspectedWindow->globalExec()), node)); } diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSLazyEventListener.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSLazyEventListener.cpp index 0d6cb57..6d75f4f 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSLazyEventListener.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSLazyEventListener.cpp @@ -35,8 +35,8 @@ namespace WebCore { static WTF::RefCountedLeakCounter eventListenerCounter("JSLazyEventListener"); #endif -JSLazyEventListener::JSLazyEventListener(const String& functionName, const String& eventParameterName, const String& code, Node* node, const String& sourceURL, int lineNumber) - : JSEventListener(0, true) +JSLazyEventListener::JSLazyEventListener(const String& functionName, const String& eventParameterName, const String& code, Node* node, const String& sourceURL, int lineNumber, DOMWrapperWorld* isolatedWorld) + : JSEventListener(0, true, isolatedWorld) , m_functionName(functionName) , m_eventParameterName(eventParameterName) , m_code(code) @@ -92,7 +92,7 @@ void JSLazyEventListener::parseCode(ScriptExecutionContext* executionContext) co if (!scriptController->isEnabled()) return; - JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(executionContext); + JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(executionContext, m_isolatedWorld.get()); if (!globalObject) return; diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSLazyEventListener.h b/src/3rdparty/webkit/WebCore/bindings/js/JSLazyEventListener.h index e3137b8..ba26ef6 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSLazyEventListener.h +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSLazyEventListener.h @@ -29,14 +29,14 @@ namespace WebCore { class JSLazyEventListener : public JSEventListener { public: - static PassRefPtr<JSLazyEventListener> create(const String& functionName, const String& eventParameterName, const String& code, Node* node, const String& sourceURL, int lineNumber) + static PassRefPtr<JSLazyEventListener> create(const String& functionName, const String& eventParameterName, const String& code, Node* node, const String& sourceURL, int lineNumber, DOMWrapperWorld* isolatedWorld) { - return adoptRef(new JSLazyEventListener(functionName, eventParameterName, code, node, sourceURL, lineNumber)); + return adoptRef(new JSLazyEventListener(functionName, eventParameterName, code, node, sourceURL, lineNumber, isolatedWorld)); } virtual ~JSLazyEventListener(); private: - JSLazyEventListener(const String& functionName, const String& eventParameterName, const String& code, Node*, const String& sourceURL, int lineNumber); + JSLazyEventListener(const String& functionName, const String& eventParameterName, const String& code, Node*, const String& sourceURL, int lineNumber, DOMWrapperWorld* isolatedWorld); virtual JSC::JSObject* jsFunction(ScriptExecutionContext*) const; virtual bool wasCreatedFromMarkup() const { return true; } diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSMessageChannelCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSMessageChannelCustom.cpp index 574e28a..d28d494 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSMessageChannelCustom.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSMessageChannelCustom.cpp @@ -36,17 +36,11 @@ void JSMessageChannel::markChildren(MarkStack& markStack) { Base::markChildren(markStack); - if (MessagePort* port = m_impl->port1()) { - DOMObject* wrapper = getCachedDOMObjectWrapper(*Heap::heap(this)->globalData(), port); - if (wrapper) - markStack.append(wrapper); - } + if (MessagePort* port = m_impl->port1()) + markDOMObjectWrapper(markStack, *Heap::heap(this)->globalData(), port); - if (MessagePort* port = m_impl->port2()) { - DOMObject* wrapper = getCachedDOMObjectWrapper(*Heap::heap(this)->globalData(), port); - if (wrapper) - markStack.append(wrapper); - } + if (MessagePort* port = m_impl->port2()) + markDOMObjectWrapper(markStack, *Heap::heap(this)->globalData(), port); } } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSMessagePortCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSMessagePortCustom.cpp index a0a92be..2c09620 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSMessagePortCustom.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSMessagePortCustom.cpp @@ -46,11 +46,8 @@ void JSMessagePort::markChildren(MarkStack& markStack) Base::markChildren(markStack); // If we have a locally entangled port, we can directly mark it as reachable. Ports that are remotely entangled are marked in-use by markActiveObjectsForContext(). - if (MessagePort* entangledPort = m_impl->locallyEntangledPort()) { - DOMObject* wrapper = getCachedDOMObjectWrapper(*Heap::heap(this)->globalData(), entangledPort); - if (wrapper) - markStack.append(wrapper); - } + if (MessagePort* entangledPort = m_impl->locallyEntangledPort()) + markDOMObjectWrapper(markStack, *Heap::heap(this)->globalData(), entangledPort); m_impl->markEventListeners(markStack); } @@ -61,7 +58,7 @@ JSValue JSMessagePort::addEventListener(ExecState* exec, const ArgList& args) if (!listener.isObject()) return jsUndefined(); - impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec)); + impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); return jsUndefined(); } @@ -71,7 +68,7 @@ JSValue JSMessagePort::removeEventListener(ExecState* exec, const ArgList& args) if (!listener.isObject()) return jsUndefined(); - impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec)); + impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); return jsUndefined(); } diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSNodeCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSNodeCustom.cpp index 4e7d622..2a4aa80 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSNodeCustom.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSNodeCustom.cpp @@ -114,7 +114,7 @@ JSValue JSNode::addEventListener(ExecState* exec, const ArgList& args) if (!listener.isObject()) return jsUndefined(); - impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false), args.at(2).toBoolean(exec)); + impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)), args.at(2).toBoolean(exec)); return jsUndefined(); } @@ -124,7 +124,7 @@ JSValue JSNode::removeEventListener(ExecState* exec, const ArgList& args) if (!listener.isObject()) return jsUndefined(); - impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec)); + impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); return jsUndefined(); } @@ -143,10 +143,8 @@ void JSNode::markChildren(MarkStack& markStack) // the document, we need to mark the document, but we don't need to explicitly // mark any other nodes. if (node->inDocument()) { - if (Document* doc = node->ownerDocument()) { - if (DOMObject* docWrapper = getCachedDOMObjectWrapper(*Heap::heap(this)->globalData(), doc)) - markStack.append(docWrapper); - } + if (Document* doc = node->ownerDocument()) + markDOMObjectWrapper(markStack, *Heap::heap(this)->globalData(), doc); return; } diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSNodeFilterCondition.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSNodeFilterCondition.cpp index a199417..54dc020 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSNodeFilterCondition.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSNodeFilterCondition.cpp @@ -66,7 +66,7 @@ short JSNodeFilterCondition::acceptNode(JSC::ExecState* exec, Node* filterNode) if (exec->hadException()) return NodeFilter::FILTER_REJECT; - JSValue result = call(exec, m_filter, callType, callData, m_filter, args); + JSValue result = callInWorld(exec, m_filter, callType, callData, m_filter, args, currentWorld(exec)); if (exec->hadException()) return NodeFilter::FILTER_REJECT; diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSQuarantinedObjectWrapper.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSQuarantinedObjectWrapper.cpp index a0551a1..2ab2c00 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSQuarantinedObjectWrapper.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSQuarantinedObjectWrapper.cpp @@ -26,6 +26,8 @@ #include "config.h" #include "JSQuarantinedObjectWrapper.h" +#include "JSDOMBinding.h" + #include <runtime/JSGlobalObject.h> using namespace JSC; @@ -243,7 +245,8 @@ JSObject* JSQuarantinedObjectWrapper::construct(ExecState* exec, JSObject* const ConstructType unwrappedConstructType = wrapper->m_unwrappedObject->getConstructData(unwrappedConstructData); ASSERT(unwrappedConstructType != ConstructTypeNone); - JSValue unwrappedResult = JSC::construct(wrapper->unwrappedExecState(), wrapper->m_unwrappedObject, unwrappedConstructType, unwrappedConstructData, preparedArgs); + // FIXME: Quarantined objects are all in the debuggerWorld(), for now. Instead, we should remove the quarantined objects, & replace them with an isolated world? + JSValue unwrappedResult = constructInWorld(wrapper->unwrappedExecState(), wrapper->m_unwrappedObject, unwrappedConstructType, unwrappedConstructData, preparedArgs, debuggerWorld()); JSValue resultValue = wrapper->wrapOutgoingValue(wrapper->unwrappedExecState(), unwrappedResult); ASSERT(resultValue.isObject()); @@ -293,7 +296,8 @@ JSValue JSQuarantinedObjectWrapper::call(ExecState* exec, JSObject* function, JS CallType unwrappedCallType = wrapper->m_unwrappedObject->getCallData(unwrappedCallData); ASSERT(unwrappedCallType != CallTypeNone); - JSValue unwrappedResult = JSC::call(wrapper->unwrappedExecState(), wrapper->m_unwrappedObject, unwrappedCallType, unwrappedCallData, preparedThisValue, preparedArgs); + // FIXME: Quarantined objects are all in the debuggerWorld(), for now. Instead, we should remove the quarantined objects, & replace them with an isolated world? + JSValue unwrappedResult = callInWorld(wrapper->unwrappedExecState(), wrapper->m_unwrappedObject, unwrappedCallType, unwrappedCallData, preparedThisValue, preparedArgs, debuggerWorld()); JSValue result = wrapper->wrapOutgoingValue(wrapper->unwrappedExecState(), unwrappedResult); diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp index fd3742d..ba1cf22 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp @@ -54,7 +54,7 @@ JSValue JSSVGElementInstance::addEventListener(ExecState* exec, const ArgList& a if (!listener.isObject()) return jsUndefined(); - impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false), args.at(2).toBoolean(exec)); + impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)), args.at(2).toBoolean(exec)); return jsUndefined(); } @@ -64,7 +64,7 @@ JSValue JSSVGElementInstance::removeEventListener(ExecState* exec, const ArgList if (!listener.isObject()) return jsUndefined(); - impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec)); + impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); return jsUndefined(); } diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSSharedWorkerCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSSharedWorkerCustom.cpp index f21f50c..4617087 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSSharedWorkerCustom.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSSharedWorkerCustom.cpp @@ -45,11 +45,8 @@ void JSSharedWorker::markChildren(MarkStack& markStack) { Base::markChildren(markStack); - if (MessagePort* port = impl()->port()) { - DOMObject* wrapper = getCachedDOMObjectWrapper(*Heap::heap(this)->globalData(), port); - if (wrapper) - markStack.append(wrapper); - } + if (MessagePort* port = impl()->port()) + markDOMObjectWrapper(markStack, *Heap::heap(this)->globalData(), port); } } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSWebSocketCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSWebSocketCustom.cpp index bea3563..33c3fcd 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSWebSocketCustom.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSWebSocketCustom.cpp @@ -66,7 +66,7 @@ JSValue JSWebSocket::addEventListener(ExecState* exec, const ArgList& args) if (!listener.isObject()) return jsUndefined(); - impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false), args.at(2).toBoolean(exec)); + impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)), args.at(2).toBoolean(exec)); return jsUndefined(); } @@ -76,7 +76,7 @@ JSValue JSWebSocket::removeEventListener(ExecState* exec, const ArgList& args) if (!listener.isObject()) return jsUndefined(); - impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec)); + impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); return jsUndefined(); } diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSWorkerContextCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSWorkerContextCustom.cpp index e1c8a8c..490d9b1 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSWorkerContextCustom.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSWorkerContextCustom.cpp @@ -122,7 +122,7 @@ JSValue JSWorkerContext::addEventListener(ExecState* exec, const ArgList& args) if (!listener.isObject()) return jsUndefined(); - impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false), args.at(2).toBoolean(exec)); + impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)), args.at(2).toBoolean(exec)); return jsUndefined(); } @@ -132,13 +132,13 @@ JSValue JSWorkerContext::removeEventListener(ExecState* exec, const ArgList& arg if (!listener.isObject()) return jsUndefined(); - impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec)); + impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); return jsUndefined(); } JSValue JSWorkerContext::setTimeout(ExecState* exec, const ArgList& args) { - ScheduledAction* action = ScheduledAction::create(exec, args); + ScheduledAction* action = ScheduledAction::create(exec, args, currentWorld(exec)); if (exec->hadException()) return jsUndefined(); int delay = args.at(1).toInt32(exec); @@ -147,7 +147,7 @@ JSValue JSWorkerContext::setTimeout(ExecState* exec, const ArgList& args) JSValue JSWorkerContext::setInterval(ExecState* exec, const ArgList& args) { - ScheduledAction* action = ScheduledAction::create(exec, args); + ScheduledAction* action = ScheduledAction::create(exec, args, currentWorld(exec)); if (exec->hadException()) return jsUndefined(); int delay = args.at(1).toInt32(exec); diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp index 7d3f8af..7ee2720 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp @@ -53,11 +53,8 @@ void JSXMLHttpRequest::markChildren(MarkStack& markStack) { Base::markChildren(markStack); - if (XMLHttpRequestUpload* upload = m_impl->optionalUpload()) { - DOMObject* wrapper = getCachedDOMObjectWrapper(*Heap::heap(this)->globalData(), upload); - if (wrapper) - markStack.append(wrapper); - } + if (XMLHttpRequestUpload* upload = m_impl->optionalUpload()) + markDOMObjectWrapper(markStack, *Heap::heap(this)->globalData(), upload); m_impl->markEventListeners(markStack); } @@ -156,7 +153,7 @@ JSValue JSXMLHttpRequest::addEventListener(ExecState* exec, const ArgList& args) if (!listener.isObject()) return jsUndefined(); - impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false), args.at(2).toBoolean(exec)); + impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)), args.at(2).toBoolean(exec)); return jsUndefined(); } @@ -166,7 +163,7 @@ JSValue JSXMLHttpRequest::removeEventListener(ExecState* exec, const ArgList& ar if (!listener.isObject()) return jsUndefined(); - impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec)); + impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); return jsUndefined(); } diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSXMLHttpRequestUploadCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSXMLHttpRequestUploadCustom.cpp index 275d1fb..fa7cfec 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSXMLHttpRequestUploadCustom.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSXMLHttpRequestUploadCustom.cpp @@ -45,11 +45,8 @@ void JSXMLHttpRequestUpload::markChildren(MarkStack& markStack) { Base::markChildren(markStack); - if (XMLHttpRequest* xmlHttpRequest = m_impl->associatedXMLHttpRequest()) { - DOMObject* wrapper = getCachedDOMObjectWrapper(*Heap::heap(this)->globalData(), xmlHttpRequest); - if (wrapper) - markStack.append(wrapper); - } + if (XMLHttpRequest* xmlHttpRequest = m_impl->associatedXMLHttpRequest()) + markDOMObjectWrapper(markStack, *Heap::heap(this)->globalData(), xmlHttpRequest); m_impl->markEventListeners(markStack); } @@ -60,7 +57,7 @@ JSValue JSXMLHttpRequestUpload::addEventListener(ExecState* exec, const ArgList& if (!listener.isObject()) return jsUndefined(); - impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false), args.at(2).toBoolean(exec)); + impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)), args.at(2).toBoolean(exec)); return jsUndefined(); } @@ -70,7 +67,7 @@ JSValue JSXMLHttpRequestUpload::removeEventListener(ExecState* exec, const ArgLi if (!listener.isObject()) return jsUndefined(); - impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec)); + impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); return jsUndefined(); } diff --git a/src/3rdparty/webkit/WebCore/bindings/js/ScheduledAction.cpp b/src/3rdparty/webkit/WebCore/bindings/js/ScheduledAction.cpp index 93155e1..9a21b6b 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/ScheduledAction.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/ScheduledAction.cpp @@ -47,7 +47,7 @@ using namespace JSC; namespace WebCore { -ScheduledAction* ScheduledAction::create(ExecState* exec, const ArgList& args) +ScheduledAction* ScheduledAction::create(ExecState* exec, const ArgList& args, DOMWrapperWorld* isolatedWorld) { JSValue v = args.at(0); CallData callData; @@ -55,15 +55,16 @@ ScheduledAction* ScheduledAction::create(ExecState* exec, const ArgList& args) UString string = v.toString(exec); if (exec->hadException()) return 0; - return new ScheduledAction(string); + return new ScheduledAction(string, isolatedWorld); } ArgList argsTail; args.getSlice(2, argsTail); - return new ScheduledAction(v, argsTail); + return new ScheduledAction(v, argsTail, isolatedWorld); } -ScheduledAction::ScheduledAction(JSValue function, const ArgList& args) +ScheduledAction::ScheduledAction(JSValue function, const ArgList& args, DOMWrapperWorld* isolatedWorld) : m_function(function) + , m_isolatedWorld(isolatedWorld) { ArgList::const_iterator end = args.end(); for (ArgList::const_iterator it = args.begin(); it != end; ++it) @@ -102,7 +103,7 @@ void ScheduledAction::executeFunctionInContext(JSGlobalObject* globalObject, JSV args.append(m_args[i]); globalObject->globalData()->timeoutChecker.start(); - call(exec, m_function, callType, callData, thisValue, args); + callInWorld(exec, m_function, callType, callData, thisValue, args, m_isolatedWorld.get()); globalObject->globalData()->timeoutChecker.stop(); if (exec->hadException()) @@ -111,7 +112,7 @@ void ScheduledAction::executeFunctionInContext(JSGlobalObject* globalObject, JSV void ScheduledAction::execute(Document* document) { - JSDOMWindow* window = toJSDOMWindow(document->frame()); + JSDOMWindow* window = toJSDOMWindow(document->frame(), m_isolatedWorld.get()); if (!window) return; @@ -125,7 +126,7 @@ void ScheduledAction::execute(Document* document) executeFunctionInContext(window, window->shell()); Document::updateStyleForAllDocuments(); } else - frame->script()->executeScript(m_code); + frame->script()->executeScriptInIsolatedWorld(m_isolatedWorld.get(), m_code); frame->script()->setProcessingTimerCallback(false); } diff --git a/src/3rdparty/webkit/WebCore/bindings/js/ScheduledAction.h b/src/3rdparty/webkit/WebCore/bindings/js/ScheduledAction.h index 2cd36ed..4ea727d 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/ScheduledAction.h +++ b/src/3rdparty/webkit/WebCore/bindings/js/ScheduledAction.h @@ -21,6 +21,7 @@ #define ScheduledAction_h #include "PlatformString.h" +#include <JSDOMBinding.h> #include <runtime/JSCell.h> #include <runtime/Protect.h> #include <wtf/Vector.h> @@ -41,14 +42,15 @@ namespace WebCore { */ class ScheduledAction { public: - static ScheduledAction* create(JSC::ExecState*, const JSC::ArgList&); + static ScheduledAction* create(JSC::ExecState*, const JSC::ArgList&, DOMWrapperWorld* isolatedWorld); void execute(ScriptExecutionContext*); private: - ScheduledAction(JSC::JSValue function, const JSC::ArgList&); - ScheduledAction(const String& code) + ScheduledAction(JSC::JSValue function, const JSC::ArgList&, DOMWrapperWorld* isolatedWorld); + ScheduledAction(const String& code, DOMWrapperWorld* isolatedWorld) : m_code(code) + , m_isolatedWorld(isolatedWorld) { } @@ -61,6 +63,7 @@ namespace WebCore { JSC::ProtectedJSValue m_function; Vector<JSC::ProtectedJSValue> m_args; String m_code; + RefPtr<DOMWrapperWorld> m_isolatedWorld; }; } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/bindings/js/ScriptCachedFrameData.cpp b/src/3rdparty/webkit/WebCore/bindings/js/ScriptCachedFrameData.cpp index 77b8ca4..e01324e 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/ScriptCachedFrameData.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/ScriptCachedFrameData.cpp @@ -48,8 +48,9 @@ ScriptCachedFrameData::ScriptCachedFrameData(Frame* frame) JSLock lock(SilenceAssertionsOnly); ScriptController* scriptController = frame->script(); - if (scriptController->haveWindowShell()) { - m_window = scriptController->windowShell()->window(); + // FIXME: explicitly save and restore isolated worlds' global objects when using the back/forward cache. <rdar://problem/7328111> + if (JSDOMWindowShell* windowShell = scriptController->existingWindowShell(mainThreadNormalWorld())) { + m_window = windowShell->window(); scriptController->attachDebugger(0); } } @@ -70,11 +71,11 @@ void ScriptCachedFrameData::restore(Frame* frame) JSLock lock(SilenceAssertionsOnly); ScriptController* scriptController = frame->script(); - if (scriptController->haveWindowShell()) { - JSDOMWindowShell* windowShell = scriptController->windowShell(); - if (m_window) { + // FIXME: explicitly save and restore isolated worlds' global objects when using the back/forward cache. <rdar://problem/7328111> + if (JSDOMWindowShell* windowShell = scriptController->existingWindowShell(mainThreadNormalWorld())) { + if (m_window) windowShell->setWindow(m_window.get()); - } else { + else { windowShell->setWindow(frame->domWindow()); scriptController->attachDebugger(page->debugger()); windowShell->window()->setProfileGroup(page->group().identifier()); diff --git a/src/3rdparty/webkit/WebCore/bindings/js/ScriptController.cpp b/src/3rdparty/webkit/WebCore/bindings/js/ScriptController.cpp index 54acc90..4a1d413 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/ScriptController.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/ScriptController.cpp @@ -21,6 +21,7 @@ #include "config.h" #include "ScriptController.h" +#include "CString.h" #include "Event.h" #include "EventNames.h" #include "Frame.h" @@ -38,12 +39,18 @@ #include "npruntime_impl.h" #include "runtime_root.h" #include <debugger/Debugger.h> +#include <runtime/InitializeThreading.h> #include <runtime/JSLock.h> using namespace JSC; namespace WebCore { +void ScriptController::initializeThreading() +{ + JSC::initializeThreading(); +} + ScriptController::ScriptController(Frame* frame) : m_frame(frame) , m_handlerLineNumber(0) @@ -71,8 +78,11 @@ ScriptController::ScriptController(Frame* frame) ScriptController::~ScriptController() { - if (m_windowShell) { - m_windowShell = 0; + if (!m_windowShells.isEmpty()) { + for (ShellMap::iterator iter = m_windowShells.begin(); iter != m_windowShells.end(); ++iter) + iter->first->forgetScriptController(this); + + m_windowShells.clear(); // It's likely that releasing the global object has created a lot of garbage. gcController().garbageCollectSoon(); @@ -81,7 +91,7 @@ ScriptController::~ScriptController() disconnectPlatformScriptObjects(); } -ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode) +ScriptValue ScriptController::evaluateInWorld(const ScriptSourceCode& sourceCode, DOMWrapperWorld* world) { const SourceCode& jsSourceCode = sourceCode.jsSourceCode(); String sourceURL = jsSourceCode.provider()->url(); @@ -94,12 +104,12 @@ ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode) // evaluate code. Returns the JS return value or 0 // if there was none, an error occured or the type couldn't be converted. - initScriptIfNeeded(); // inlineCode is true for <a href="javascript:doSomething()"> // and false for <script>doSomething()</script>. Check if it has the // expected value in all cases. // See smart window.open policy for where this is used. - ExecState* exec = m_windowShell->window()->globalExec(); + JSDOMWindowShell* shell = windowShell(world); + ExecState* exec = shell->window()->globalExec(); const String* savedSourceURL = m_sourceURL; m_sourceURL = &sourceURL; @@ -107,9 +117,9 @@ ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode) RefPtr<Frame> protect = m_frame; - m_windowShell->window()->globalData()->timeoutChecker.start(); - Completion comp = JSC::evaluate(exec, exec->dynamicGlobalObject()->globalScopeChain(), jsSourceCode, m_windowShell); - m_windowShell->window()->globalData()->timeoutChecker.stop(); + exec->globalData().timeoutChecker.start(); + Completion comp = WebCore::evaluateInWorld(exec, exec->dynamicGlobalObject()->globalScopeChain(), jsSourceCode, shell, world); + exec->globalData().timeoutChecker.stop(); // Evaluating the JavaScript could cause the frame to be deallocated // so we start the keep alive timer here. @@ -127,52 +137,114 @@ ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode) return JSValue(); } -void ScriptController::evaluateInIsolatedWorld(unsigned /* worldID */, const Vector<ScriptSourceCode>& sourceCode) +ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode) +{ + return evaluateInWorld(sourceCode, mainThreadNormalWorld()); +} + +// An DOMWrapperWorld other than the thread's normal world. +class IsolatedWorld : public DOMWrapperWorld { +public: + IsolatedWorld(JSGlobalData* globalData) + : DOMWrapperWorld(globalData) + { + JSGlobalData::ClientData* clientData = globalData->clientData; + ASSERT(clientData); + static_cast<WebCoreJSClientData*>(clientData)->rememberWorld(this); + } + + static PassRefPtr<IsolatedWorld> create(JSGlobalData* globalData) { return adoptRef(new IsolatedWorld(globalData)); } +}; + +static PassRefPtr<IsolatedWorld> findWorld(unsigned worldID) +{ + if (!worldID) + return IsolatedWorld::create(JSDOMWindow::commonJSGlobalData()); + + typedef HashMap<unsigned, RefPtr<IsolatedWorld> > WorldMap; + DEFINE_STATIC_LOCAL(WorldMap, isolatedWorlds, ()); + + WorldMap::iterator iter = isolatedWorlds.find(worldID); + if (iter != isolatedWorlds.end()) + return iter->second; + + RefPtr<IsolatedWorld> newWorld = IsolatedWorld::create(JSDOMWindow::commonJSGlobalData()); + isolatedWorlds.add(worldID, newWorld); + return newWorld; +} + +JSDOMWindow* ScriptController::globalObject(unsigned worldID) +{ + RefPtr<DOMWrapperWorld> world = findWorld(worldID); + return windowShell(world.get())->window(); +} + +ScriptValue ScriptController::evaluateInIsolatedWorld(unsigned worldID, const ScriptSourceCode& sourceCode) +{ + RefPtr<DOMWrapperWorld> world = findWorld(worldID); + return evaluateInWorld(sourceCode, world.get()); +} + +void ScriptController::evaluateInIsolatedWorld(unsigned worldID, const Vector<ScriptSourceCode>& sourceCode) { - // FIXME: Actually support isolated worlds! + RefPtr<DOMWrapperWorld> world = findWorld(worldID); + unsigned size = sourceCode.size(); for (unsigned i = 0; i < size; ++i) - evaluate(sourceCode[i]); + evaluateInWorld(sourceCode[i], world.get()); } void ScriptController::clearWindowShell() { - if (!m_windowShell) + if (m_windowShells.isEmpty()) return; JSLock lock(SilenceAssertionsOnly); // Clear the debugger from the current window before setting the new window. + DOMWrapperWorld* debugWorld = debuggerWorld(); attachDebugger(0); - m_windowShell->window()->willRemoveFromWindowShell(); - m_windowShell->setWindow(m_frame->domWindow()); + for (ShellMap::iterator iter = m_windowShells.begin(); iter != m_windowShells.end(); ++iter) { + DOMWrapperWorld* world = iter->first; + JSDOMWindowShell* windowShell = iter->second; + windowShell->window()->willRemoveFromWindowShell(); + windowShell->setWindow(m_frame->domWindow()); - if (Page* page = m_frame->page()) { - attachDebugger(page->debugger()); - m_windowShell->window()->setProfileGroup(page->group().identifier()); + if (Page* page = m_frame->page()) { + if (world == debugWorld) + attachDebugger(page->debugger()); + windowShell->window()->setProfileGroup(page->group().identifier()); + } } // There is likely to be a lot of garbage now. gcController().garbageCollectSoon(); } -void ScriptController::initScript() +JSDOMWindowShell* ScriptController::initScript(DOMWrapperWorld* world) { - if (m_windowShell) - return; + ASSERT(!m_windowShells.contains(world)); JSLock lock(SilenceAssertionsOnly); - m_windowShell = new JSDOMWindowShell(m_frame->domWindow()); - m_windowShell->window()->updateDocument(); + JSDOMWindowShell* windowShell = new JSDOMWindowShell(m_frame->domWindow()); + m_windowShells.add(world, windowShell); + world->rememberScriptController(this); + windowShell->window()->updateDocument(world); if (Page* page = m_frame->page()) { - attachDebugger(page->debugger()); - m_windowShell->window()->setProfileGroup(page->group().identifier()); + if (world == debuggerWorld()) + attachDebugger(page->debugger()); + windowShell->window()->setProfileGroup(page->group().identifier()); + } + + { + EnterDOMWrapperWorld worldEntry(*JSDOMWindow::commonJSGlobalData(), world); + m_frame->loader()->dispatchWindowObjectAvailable(); } - m_frame->loader()->dispatchWindowObjectAvailable(); + return windowShell; } bool ScriptController::processingUserGesture() const @@ -182,10 +254,11 @@ bool ScriptController::processingUserGesture() const bool ScriptController::processingUserGestureEvent() const { - if (!m_windowShell) + JSDOMWindowShell* shell = existingWindowShell(mainThreadNormalWorld()); + if (!shell) return false; - if (Event* event = m_windowShell->window()->currentEvent()) { + if (Event* event = shell->window()->currentEvent()) { if (event->createdByDOM()) return false; @@ -243,13 +316,16 @@ bool ScriptController::isEnabled() void ScriptController::attachDebugger(JSC::Debugger* debugger) { - if (!m_windowShell) + // FIXME: Should be able to debug isolated worlds. + JSDOMWindowShell* shell = existingWindowShell(debuggerWorld()); + if (!shell) return; + JSDOMWindow* globalObject = shell->window(); if (debugger) - debugger->attach(m_windowShell->window()); - else if (JSC::Debugger* currentDebugger = m_windowShell->window()->debugger()) - currentDebugger->detach(m_windowShell->window()); + debugger->attach(globalObject); + else if (JSC::Debugger* currentDebugger = globalObject->debugger()) + currentDebugger->detach(globalObject); } void ScriptController::updateDocument() @@ -258,8 +334,8 @@ void ScriptController::updateDocument() return; JSLock lock(SilenceAssertionsOnly); - if (m_windowShell) - m_windowShell->window()->updateDocument(); + for (ShellMap::iterator iter = m_windowShells.begin(); iter != m_windowShells.end(); ++iter) + iter->second->window()->updateDocument(iter->first); } void ScriptController::updateSecurityOrigin() @@ -274,7 +350,7 @@ Bindings::RootObject* ScriptController::bindingRootObject() if (!m_bindingRootObject) { JSLock lock(SilenceAssertionsOnly); - m_bindingRootObject = Bindings::RootObject::create(0, globalObject()); + m_bindingRootObject = Bindings::RootObject::create(0, globalObject(pluginWorld())); } return m_bindingRootObject.get(); } @@ -285,7 +361,7 @@ PassRefPtr<Bindings::RootObject> ScriptController::createRootObject(void* native if (it != m_rootObjects.end()) return it->second; - RefPtr<Bindings::RootObject> rootObject = Bindings::RootObject::create(nativeHandle, globalObject()); + RefPtr<Bindings::RootObject> rootObject = Bindings::RootObject::create(nativeHandle, globalObject(pluginWorld())); m_rootObjects.set(nativeHandle, rootObject); return rootObject.release(); @@ -300,7 +376,7 @@ NPObject* ScriptController::windowScriptNPObject() // JavaScript is enabled, so there is a JavaScript window object. // Return an NPObject bound to the window object. JSC::JSLock lock(SilenceAssertionsOnly); - JSObject* win = windowShell()->window(); + JSObject* win = windowShell(pluginWorld())->window(); ASSERT(win); Bindings::RootObject* root = bindingRootObject(); m_windowScriptNPObject = _NPN_CreateScriptObject(0, win, root); @@ -334,8 +410,9 @@ JSObject* ScriptController::jsObjectForPluginElement(HTMLPlugInElement* plugin) // Create a JSObject bound to this element JSLock lock(SilenceAssertionsOnly); - ExecState* exec = globalObject()->globalExec(); - JSValue jsElementValue = toJS(exec, globalObject(), plugin); + JSDOMWindow* globalObj = globalObject(pluginWorld()); + // FIXME: is normal okay? - used for NP plugins? + JSValue jsElementValue = toJS(globalObj->globalExec(), globalObj, plugin); if (!jsElementValue || !jsElementValue.isObject()) return 0; @@ -391,4 +468,44 @@ void ScriptController::clearScriptObjects() #endif } +ScriptValue ScriptController::executeScriptInIsolatedWorld(unsigned worldID, const String& script, bool forceUserGesture) +{ + ScriptSourceCode sourceCode(script, forceUserGesture ? KURL() : m_frame->loader()->url()); + + if (!isEnabled() || isPaused()) + return ScriptValue(); + + bool wasInExecuteScript = m_inExecuteScript; + m_inExecuteScript = true; + + ScriptValue result = evaluateInIsolatedWorld(worldID, sourceCode); + + if (!wasInExecuteScript) { + m_inExecuteScript = false; + Document::updateStyleForAllDocuments(); + } + + return result; +} + +ScriptValue ScriptController::executeScriptInIsolatedWorld(DOMWrapperWorld* world, const String& script, bool forceUserGesture) +{ + ScriptSourceCode sourceCode(script, forceUserGesture ? KURL() : m_frame->loader()->url()); + + if (!isEnabled() || isPaused()) + return ScriptValue(); + + bool wasInExecuteScript = m_inExecuteScript; + m_inExecuteScript = true; + + ScriptValue result = evaluateInWorld(sourceCode, world); + + if (!wasInExecuteScript) { + m_inExecuteScript = false; + Document::updateStyleForAllDocuments(); + } + + return result; +} + } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/bindings/js/ScriptController.h b/src/3rdparty/webkit/WebCore/bindings/js/ScriptController.h index bd4b65e..f2a497d 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/ScriptController.h +++ b/src/3rdparty/webkit/WebCore/bindings/js/ScriptController.h @@ -63,31 +63,49 @@ class XSSAuditor; typedef HashMap<void*, RefPtr<JSC::Bindings::RootObject> > RootObjectMap; class ScriptController { + typedef WTF::HashMap<DOMWrapperWorld*, JSC::ProtectedPtr<JSDOMWindowShell> > ShellMap; + public: ScriptController(Frame*); ~ScriptController(); - bool haveWindowShell() const { return m_windowShell; } - JSDOMWindowShell* windowShell() + JSDOMWindowShell* windowShell(DOMWrapperWorld* world) + { + ShellMap::iterator iter = m_windowShells.find(world); + return (iter != m_windowShells.end()) ? iter->second.get() : initScript(world); + } + JSDOMWindowShell* existingWindowShell(DOMWrapperWorld* world) const + { + ShellMap::const_iterator iter = m_windowShells.find(world); + return (iter != m_windowShells.end()) ? iter->second.get() : 0; + } + JSDOMWindow* globalObject(DOMWrapperWorld* world) { - initScriptIfNeeded(); - return m_windowShell; + return windowShell(world)->window(); } + JSDOMWindow* globalObject(unsigned worldID); - JSDOMWindow* globalObject() + void forgetWorld(DOMWrapperWorld* world) { - initScriptIfNeeded(); - return m_windowShell->window(); + m_windowShells.remove(world); } ScriptValue executeScript(const ScriptSourceCode&); ScriptValue executeScript(const String& script, bool forceUserGesture = false); + ScriptValue executeScriptInIsolatedWorld(unsigned worldID, const String& script, bool forceUserGesture = false); + ScriptValue executeScriptInIsolatedWorld(DOMWrapperWorld* world, const String& script, bool forceUserGesture = false); // Returns true if argument is a JavaScript URL. bool executeIfJavaScriptURL(const KURL&, bool userGesture = false, bool replaceDocument = true); + // This function must be called from the main thread. It is safe to call it repeatedly. + // Darwin is an exception to this rule: it is OK to call this function from any thread, even reentrantly. + static void initializeThreading(); + ScriptValue evaluate(const ScriptSourceCode&); - void evaluateInIsolatedWorld(unsigned worldID, const Vector<ScriptSourceCode>&); + ScriptValue evaluateInWorld(const ScriptSourceCode&, DOMWrapperWorld*); + ScriptValue evaluateInIsolatedWorld(unsigned /*worldID*/, const ScriptSourceCode&); + void evaluateInIsolatedWorld(unsigned /*worldID*/, const Vector<ScriptSourceCode>&); void setEventHandlerLineNumber(int lineno) { m_handlerLineNumber = lineno; } int eventHandlerLineNumber() { return m_handlerLineNumber; } @@ -144,19 +162,14 @@ public: XSSAuditor* xssAuditor() { return m_XSSAuditor.get(); } private: - void initScriptIfNeeded() - { - if (!m_windowShell) - initScript(); - } - void initScript(); + JSDOMWindowShell* initScript(DOMWrapperWorld* world); void disconnectPlatformScriptObjects(); bool processingUserGestureEvent() const; bool isJavaScriptAnchorNavigation() const; - JSC::ProtectedPtr<JSDOMWindowShell> m_windowShell; + ShellMap m_windowShells; Frame* m_frame; int m_handlerLineNumber; const String* m_sourceURL; diff --git a/src/3rdparty/webkit/WebCore/bindings/js/ScriptControllerMac.mm b/src/3rdparty/webkit/WebCore/bindings/js/ScriptControllerMac.mm index e6a654f..21ec0f2 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/ScriptControllerMac.mm +++ b/src/3rdparty/webkit/WebCore/bindings/js/ScriptControllerMac.mm @@ -114,7 +114,7 @@ WebScriptObject* ScriptController::windowScriptObject() if (!m_windowScriptObject) { JSC::JSLock lock(JSC::SilenceAssertionsOnly); JSC::Bindings::RootObject* root = bindingRootObject(); - m_windowScriptObject = [WebScriptObject scriptObjectForJSObject:toRef(windowShell()) originRootObject:root rootObject:root]; + m_windowScriptObject = [WebScriptObject scriptObjectForJSObject:toRef(windowShell(pluginWorld())) originRootObject:root rootObject:root]; } ASSERT([m_windowScriptObject.get() isKindOfClass:[DOMAbstractView class]]); diff --git a/src/3rdparty/webkit/WebCore/bindings/js/ScriptEventListener.cpp b/src/3rdparty/webkit/WebCore/bindings/js/ScriptEventListener.cpp index 0b0047b..8399c7a 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/ScriptEventListener.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/ScriptEventListener.cpp @@ -71,7 +71,7 @@ PassRefPtr<JSLazyEventListener> createAttributeEventListener(Node* node, Attribu sourceURL = node->document()->url().string(); } - return JSLazyEventListener::create(attr->localName().string(), eventParameterName(node->isSVGElement()), attr->value(), node, sourceURL, lineNumber); + return JSLazyEventListener::create(attr->localName().string(), eventParameterName(node->isSVGElement()), attr->value(), node, sourceURL, lineNumber, mainThreadNormalWorld()); } PassRefPtr<JSLazyEventListener> createAttributeEventListener(Frame* frame, Attribute* attr) @@ -93,7 +93,7 @@ PassRefPtr<JSLazyEventListener> createAttributeEventListener(Frame* frame, Attri lineNumber = scriptController->eventHandlerLineNumber(); sourceURL = frame->document()->url().string(); - return JSLazyEventListener::create(attr->localName().string(), eventParameterName(frame->document()->isSVGDocument()), attr->value(), 0, sourceURL, lineNumber); + return JSLazyEventListener::create(attr->localName().string(), eventParameterName(frame->document()->isSVGDocument()), attr->value(), 0, sourceURL, lineNumber, mainThreadNormalWorld()); } String getEventListenerHandlerBody(ScriptExecutionContext* context, ScriptState* scriptState, EventListener* eventListener) diff --git a/src/3rdparty/webkit/WebCore/bindings/js/ScriptFunctionCall.cpp b/src/3rdparty/webkit/WebCore/bindings/js/ScriptFunctionCall.cpp index 46e80ac..91b2a57 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/ScriptFunctionCall.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/ScriptFunctionCall.cpp @@ -123,7 +123,8 @@ ScriptValue ScriptFunctionCall::call(bool& hadException, bool reportExceptions) if (callType == CallTypeNone) return ScriptValue(); - JSValue result = JSC::call(m_exec, function, callType, callData, thisObject, m_arguments); + // FIXME: Should this function take a worldID? - only used by inspector? + JSValue result = callInWorld(m_exec, function, callType, callData, thisObject, m_arguments, debuggerWorld()); if (m_exec->hadException()) { if (reportExceptions) reportException(m_exec, m_exec->exception()); @@ -161,7 +162,8 @@ ScriptObject ScriptFunctionCall::construct(bool& hadException, bool reportExcept if (constructType == ConstructTypeNone) return ScriptObject(); - JSValue result = JSC::construct(m_exec, constructor, constructType, constructData, m_arguments); + // FIXME: Currently this method constructs objects in debuggerWorld(). We could use the current world, or pass a worldID to this function? + JSValue result = constructInWorld(m_exec, constructor, constructType, constructData, m_arguments, debuggerWorld()); if (m_exec->hadException()) { if (reportExceptions) reportException(m_exec, m_exec->exception()); diff --git a/src/3rdparty/webkit/WebCore/bindings/js/ScriptObjectQuarantine.cpp b/src/3rdparty/webkit/WebCore/bindings/js/ScriptObjectQuarantine.cpp index b48556e..313530f 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/ScriptObjectQuarantine.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/ScriptObjectQuarantine.cpp @@ -72,7 +72,7 @@ bool getQuarantinedScriptObject(Database* database, ScriptObject& quarantinedObj if (!frame) return false; - JSDOMGlobalObject* globalObject = toJSDOMWindow(frame); + JSDOMGlobalObject* globalObject = toJSDOMWindow(frame, debuggerWorld()); ExecState* exec = globalObject->globalExec(); JSLock lock(SilenceAssertionsOnly); @@ -89,7 +89,7 @@ bool getQuarantinedScriptObject(Storage* storage, ScriptObject& quarantinedObjec Frame* frame = storage->frame(); ASSERT(frame); - JSDOMGlobalObject* globalObject = toJSDOMWindow(frame); + JSDOMGlobalObject* globalObject = toJSDOMWindow(frame, debuggerWorld()); ExecState* exec = globalObject->globalExec(); JSLock lock(SilenceAssertionsOnly); @@ -116,7 +116,7 @@ bool getQuarantinedScriptObject(DOMWindow* domWindow, ScriptObject& quarantinedO { ASSERT(domWindow); - JSDOMWindow* window = toJSDOMWindow(domWindow->frame()); + JSDOMWindow* window = toJSDOMWindow(domWindow->frame(), debuggerWorld()); ExecState* exec = window->globalExec(); JSLock lock(SilenceAssertionsOnly); diff --git a/src/3rdparty/webkit/WebCore/bindings/js/ScriptSourceCode.h b/src/3rdparty/webkit/WebCore/bindings/js/ScriptSourceCode.h index 1b05ded..32d6298 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/ScriptSourceCode.h +++ b/src/3rdparty/webkit/WebCore/bindings/js/ScriptSourceCode.h @@ -44,6 +44,7 @@ public: ScriptSourceCode(const String& source, const KURL& url = KURL(), int startLine = 1) : m_provider(StringSourceProvider::create(source, url.isNull() ? String() : url.string())) , m_code(m_provider, startLine) + , m_url(url) { } @@ -59,10 +60,17 @@ public: const String& source() const { return m_provider->source(); } + int startLine() const { return m_code.firstLine(); } + + const KURL& url() const { return m_url; } + private: RefPtr<ScriptSourceProvider> m_provider; JSC::SourceCode m_code; + + KURL m_url; + }; } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/bindings/js/ScriptState.cpp b/src/3rdparty/webkit/WebCore/bindings/js/ScriptState.cpp index 8bfa33d..60ba2a0 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/ScriptState.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/ScriptState.cpp @@ -32,6 +32,7 @@ #include "ScriptState.h" #include "Frame.h" +#include "JSDOMWindowBase.h" #include "Node.h" #include "Page.h" @@ -49,12 +50,12 @@ ScriptState* scriptStateFromNode(Node* node) return 0; if (!frame->script()->isEnabled()) return 0; - return frame->script()->globalObject()->globalExec(); + return frame->script()->globalObject(mainThreadCurrentWorld())->globalExec(); } ScriptState* scriptStateFromPage(Page* page) { - return page->mainFrame()->script()->globalObject()->globalExec(); + return page->mainFrame()->script()->globalObject(mainThreadCurrentWorld())->globalExec(); } } diff --git a/src/3rdparty/webkit/WebCore/bindings/js/ScriptState.h b/src/3rdparty/webkit/WebCore/bindings/js/ScriptState.h index fa5c4a8..279234e 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/ScriptState.h +++ b/src/3rdparty/webkit/WebCore/bindings/js/ScriptState.h @@ -35,6 +35,7 @@ #include "JSDOMBinding.h" namespace WebCore { + class DOMWrapperWorld; class Node; class Page; diff --git a/src/3rdparty/webkit/WebCore/bindings/js/WorkerScriptController.cpp b/src/3rdparty/webkit/WebCore/bindings/js/WorkerScriptController.cpp index 3590dad..b66b0e8 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/WorkerScriptController.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/WorkerScriptController.cpp @@ -52,6 +52,7 @@ WorkerScriptController::WorkerScriptController(WorkerContext* workerContext) , m_workerContext(workerContext) , m_executionForbidden(false) { + m_globalData->clientData = new WebCoreJSClientData(m_globalData.get()); } WorkerScriptController::~WorkerScriptController() @@ -122,7 +123,7 @@ ScriptValue WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, ExecState* exec = m_workerContextWrapper->globalExec(); m_workerContextWrapper->globalData()->timeoutChecker.start(); - Completion comp = JSC::evaluate(exec, exec->dynamicGlobalObject()->globalScopeChain(), sourceCode.jsSourceCode(), m_workerContextWrapper); + Completion comp = evaluateInWorld(exec, exec->dynamicGlobalObject()->globalScopeChain(), sourceCode.jsSourceCode(), m_workerContextWrapper, currentWorld(exec)); m_workerContextWrapper->globalData()->timeoutChecker.stop(); if (comp.complType() == Normal || comp.complType() == ReturnValue) diff --git a/src/3rdparty/webkit/WebCore/bindings/js/WorkerScriptController.h b/src/3rdparty/webkit/WebCore/bindings/js/WorkerScriptController.h index bb33f60..c820cd9 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/WorkerScriptController.h +++ b/src/3rdparty/webkit/WebCore/bindings/js/WorkerScriptController.h @@ -62,6 +62,9 @@ namespace WebCore { void setException(ScriptValue); void forbidExecution(); + + JSC::JSGlobalData* globalData() { return m_globalData.get(); } + private: void initScriptIfNeeded() { diff --git a/src/3rdparty/webkit/WebCore/bindings/scripts/CodeGeneratorJS.pm b/src/3rdparty/webkit/WebCore/bindings/scripts/CodeGeneratorJS.pm index ff7b52f..d8367ac 100644 --- a/src/3rdparty/webkit/WebCore/bindings/scripts/CodeGeneratorJS.pm +++ b/src/3rdparty/webkit/WebCore/bindings/scripts/CodeGeneratorJS.pm @@ -292,7 +292,7 @@ sub GenerateGetOwnPropertySlotBody my @getOwnPropertySlotImpl = (); - if ($interfaceName eq "NamedNodeMap" or $interfaceName eq "HTMLCollection") { + if ($interfaceName eq "NamedNodeMap" or $interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") { push(@getOwnPropertySlotImpl, " ${namespaceMaybe}JSValue proto = prototype();\n"); push(@getOwnPropertySlotImpl, " if (proto.isObject() && static_cast<${namespaceMaybe}JSObject*>(asObject(proto))->hasProperty(exec, propertyName))\n"); push(@getOwnPropertySlotImpl, " return false;\n\n"); @@ -369,7 +369,7 @@ sub GenerateGetOwnPropertyDescriptorBody my @getOwnPropertyDescriptorImpl = (); - if ($interfaceName eq "NamedNodeMap" or $interfaceName eq "HTMLCollection") { + if ($interfaceName eq "NamedNodeMap" or $interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") { push(@getOwnPropertyDescriptorImpl, " ${namespaceMaybe}JSValue proto = prototype();\n"); push(@getOwnPropertyDescriptorImpl, " if (proto.isObject() && static_cast<${namespaceMaybe}JSObject*>(asObject(proto))->hasProperty(exec, propertyName))\n"); push(@getOwnPropertyDescriptorImpl, " return false;\n\n"); @@ -658,6 +658,12 @@ sub GenerateHeader # Custom lookupSetter function push(@headerContent, " virtual JSC::JSValue lookupSetter(JSC::ExecState*, const JSC::Identifier& propertyName);\n") if $dataNode->extendedAttributes->{"CustomLookupSetter"}; + # Override toBoolean to return false for objects that want to 'MasqueradesAsUndefined'. + if ($dataNode->extendedAttributes->{"MasqueradesAsUndefined"}) { + push(@headerContent, " virtual bool toBoolean(JSC::ExecState*) const { return false; };\n"); + $structureFlags{"JSC::MasqueradesAsUndefined"} = 1; + } + # Constructor object getter push(@headerContent, " static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*);\n") if $dataNode->extendedAttributes->{"GenerateConstructor"}; @@ -1188,19 +1194,21 @@ sub GenerateImplementation push(@implContent, " impl()->invalidateEventListeners();\n"); } - if ($interfaceName eq "Node") { - push(@implContent, " forgetDOMNode(impl()->document(), impl());\n"); - } else { - if ($podType) { - my $animatedType = $implClassName; - $animatedType =~ s/SVG/SVGAnimated/; + if (!$dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"}) { + if ($interfaceName eq "Node") { + push(@implContent, " forgetDOMNode(this, impl(), impl()->document());\n"); + } else { + if ($podType) { + my $animatedType = $implClassName; + $animatedType =~ s/SVG/SVGAnimated/; - # Special case for JSSVGNumber - if ($codeGenerator->IsSVGAnimatedType($animatedType) and $podType ne "float") { - push(@implContent, " JSSVGDynamicPODTypeWrapperCache<$podType, $animatedType>::forgetWrapper(m_impl.get());\n"); + # Special case for JSSVGNumber + if ($codeGenerator->IsSVGAnimatedType($animatedType) and $podType ne "float") { + push(@implContent, " JSSVGDynamicPODTypeWrapperCache<$podType, $animatedType>::forgetWrapper(m_impl.get());\n"); + } } + push(@implContent, " forgetDOMObject(this, impl());\n"); } - push(@implContent, " forgetDOMObject(*Heap::heap(this)->globalData(), impl());\n"); } push(@implContent, "}\n\n"); @@ -1210,7 +1218,7 @@ sub GenerateImplementation # its own special handling rather than relying on the caching that Node normally does. if ($interfaceName eq "Document") { push(@implContent, "${className}::~$className()\n"); - push(@implContent, "{\n forgetDOMObject(*Heap::heap(this)->globalData(), static_cast<${implClassName}*>(impl()));\n}\n\n"); + push(@implContent, "{\n forgetDOMObject(this, static_cast<${implClassName}*>(impl()));\n}\n\n"); } if ($needsMarkChildren && !$dataNode->extendedAttributes->{"CustomMarkFunction"}) { @@ -1476,7 +1484,7 @@ sub GenerateImplementation } else { $implIncludes{"Frame.h"} = 1; $implIncludes{"JSDOMGlobalObject.h"} = 1; - push(@implContent, " JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(imp->scriptExecutionContext());\n"); + push(@implContent, " JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(imp->scriptExecutionContext(), exec);\n"); push(@implContent, " if (!globalObject)\n"); push(@implContent, " return;\n"); } @@ -1700,7 +1708,7 @@ sub GenerateImplementation push(@implContent, " return toJS(exec, thisObj->globalObject(), static_cast<$implClassName*>(thisObj->impl())->item(slot.index()));\n"); } push(@implContent, "}\n"); - if ($interfaceName eq "HTMLCollection") { + if ($interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") { $implIncludes{"JSNode.h"} = 1; $implIncludes{"Node.h"} = 1; } @@ -1711,7 +1719,7 @@ sub GenerateImplementation push(@implContent, "{\n"); push(@implContent, " return jsNumber(exec, static_cast<$implClassName*>(impl())->item(index));\n"); push(@implContent, "}\n"); - if ($interfaceName eq "HTMLCollection") { + if ($interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") { $implIncludes{"JSNode.h"} = 1; $implIncludes{"Node.h"} = 1; } diff --git a/src/3rdparty/webkit/WebCore/bindings/scripts/CodeGeneratorV8.pm b/src/3rdparty/webkit/WebCore/bindings/scripts/CodeGeneratorV8.pm index 28562f1..95b2aa2 100644 --- a/src/3rdparty/webkit/WebCore/bindings/scripts/CodeGeneratorV8.pm +++ b/src/3rdparty/webkit/WebCore/bindings/scripts/CodeGeneratorV8.pm @@ -215,7 +215,6 @@ sub AddClassForwardIfNeeded sub GetImplementationFileName { my $iface = shift; - return "HTMLCollection.h" if $iface eq "HTMLAllCollection"; return "Event.h" if $iface eq "DOMTimeStamp"; return "NamedAttrMap.h" if $iface eq "NamedNodeMap"; return "NameNodeList.h" if $iface eq "NodeList"; @@ -307,7 +306,7 @@ sub GenerateSetDOMException my $indent = shift; my $result = ""; - $result .= $indent . "if (ec) {\n"; + $result .= $indent . "if (UNLIKELY(ec)) {\n"; $result .= $indent . " V8Proxy::setDOMException(ec);\n"; $result .= $indent . " return v8::Handle<v8::Value>();\n"; $result .= $indent . "}\n"; @@ -622,15 +621,17 @@ END push(@implContentDecls, " if (!imp->document())\n"); push(@implContentDecls, " return v8::Undefined();\n"); } - push(@implContentDecls, " $nativeType v = "); - - push(@implContentDecls, "$getterString;\n"); if ($useExceptions) { + push(@implContentDecls, " $nativeType v = "); + push(@implContentDecls, "$getterString;\n"); push(@implContentDecls, GenerateSetDOMException(" ")); + $result = "v"; + $result .= ".release()" if (IsRefPtrType($returnType)); + } else { + # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary + $result = $getterString; } - - $result = "v"; } if (IsSVGTypeNeedingContextParameter($attrType) && !$skipContext) { @@ -646,7 +647,6 @@ END my $classIndex = uc($attrType); push(@implContentDecls, " return V8DOMWrapper::convertToV8Object(V8ClassIndex::$classIndex, wrapper.release());\n"); } else { - $result .= ".release()" if (IsRefPtrType($attrType)); push(@implContentDecls, " " . ReturnNativeToJSValue($attribute->signature, $result, " ").";\n"); } @@ -784,7 +784,8 @@ END } if ($useExceptions) { - push(@implContentDecls, " V8Proxy::setDOMException(ec);\n"); + push(@implContentDecls, " if (UNLIKELY(ec))\n"); + push(@implContentDecls, " V8Proxy::setDOMException(ec);\n"); } if ($isPodType) { @@ -917,7 +918,7 @@ END if (TypeCanFailConversion($parameter)) { $implIncludes{"ExceptionCode.h"} = 1; push(@implContentDecls, -" if (!$parameterName" . (BasicTypeCanFailConversion($parameter) ? "Ok" : "") . ") {\n" . +" if (UNLIKELY(!$parameterName" . (BasicTypeCanFailConversion($parameter) ? "Ok" : "") . ")) {\n" . " V8Proxy::setDOMException(TYPE_MISMATCH_ERR);\n" . " return v8::Handle<v8::Value>();\n" . " }\n"); @@ -926,7 +927,7 @@ END if ($parameter->extendedAttributes->{"IsIndex"}) { $implIncludes{"ExceptionCode.h"} = 1; push(@implContentDecls, -" if ($parameterName < 0) {\n" . +" if (UNLIKELY($parameterName < 0)) {\n" . " V8Proxy::setDOMException(INDEX_SIZE_ERR);\n" . " return v8::Handle<v8::Value>();\n" . " }\n"); @@ -1322,6 +1323,13 @@ END $template = "instance"; } + my $conditional = ""; + if ($attrExt->{"EnabledAtRuntime"}) { + # Only call Set()/SetAccessor() if this method should be enabled + $enable_function = $interfaceName . $codeGenerator->WK_ucfirst($function->signature->name); + $conditional = "if (V8Custom::v8${enable_function}Enabled())\n"; + } + if ($attrExt->{"DoNotCheckDomainSecurity"} && ($dataNode->extendedAttributes->{"CheckDomainSecurity"} || $interfaceName eq "DOMWindow")) { # Mark the accessor as ReadOnly and set it on the proto object so @@ -1342,7 +1350,7 @@ END push(@implContent, <<END); // $commentInfo - $template->SetAccessor( + $conditional $template->SetAccessor( v8::String::New("$name"), ${interfaceName}Internal::${name}AttrGetter, 0, @@ -1370,7 +1378,7 @@ END push(@implContent, <<END); // $commentInfo - ${template}->Set( + $conditional ${template}->Set( v8::String::New("$name"), $templateFunction, static_cast<v8::PropertyAttribute>($property_attributes)); @@ -1388,7 +1396,7 @@ END } # Set the class name. This is used when printing objects. - push(@implContent, " desc->SetClassName(v8::String::New(\"" . GetClassName(${interfaceName}) . "\"));\n"); + push(@implContent, " desc->SetClassName(v8::String::New(\"${interfaceName}\"));\n"); if ($has_constants) { push(@implContent, <<END); @@ -1530,6 +1538,9 @@ sub GenerateFunctionCallString() } $functionString .= ")"; + my $return = "result"; + my $returnIsRef = IsRefPtrType($returnType); + if ($nodeToReturn) { # Special case for insertBefore, replaceChild, removeChild and # appendChild functions from Node. @@ -1550,16 +1561,18 @@ sub GenerateFunctionCallString() $indent . "$functionString;\n"; } elsif ($returnsListItemPodType) { $result .= $indent . "RefPtr<SVGPODListItem<$nativeReturnType> > result = $functionString;\n"; - } else { + } elsif (@{$function->raisesExceptions} or $returnsPodType or $isPodType or IsSVGTypeNeedingContextParameter($returnType)) { $result .= $indent . $nativeReturnType . " result = $functionString;\n"; + } else { + # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary + $return = $functionString; + $returnIsRef = 0; } if (@{$function->raisesExceptions}) { $result .= GenerateSetDOMException($indent); } - my $return = "result"; - # If the return type is a POD type, separate out the wrapper generation if ($returnsListItemPodType) { $result .= $indent . "RefPtr<V8SVGPODTypeWrapper<" . $nativeReturnType . "> > wrapper = "; @@ -1602,7 +1615,7 @@ sub GenerateFunctionCallString() my $classIndex = uc($returnType); $result .= $indent . "return V8DOMWrapper::convertToV8Object(V8ClassIndex::$classIndex, wrapper.release());\n"; } else { - $return .= ".release()" if (IsRefPtrType($returnType)); + $return .= ".release()" if ($returnIsRef); $result .= $indent . ReturnNativeToJSValue($function->signature, $return, $indent) . ";\n"; } @@ -1610,15 +1623,6 @@ sub GenerateFunctionCallString() } -# Get the class name used for printing javascript DOM-object wrappers. -sub GetClassName -{ - my $type = shift; - return "HTMLCollection" if $type eq "HTMLAllCollection"; - return $type; -} - - sub GetTypeFromSignature { my $signature = shift; @@ -1696,6 +1700,7 @@ sub IsRefPtrType return 1 if $type eq "EventListener"; return 1 if $type eq "FileList"; return 1 if $type eq "HTMLCollection"; + return 1 if $type eq "HTMLAllCollection"; return 1 if $type eq "HTMLDocument"; return 1 if $type eq "HTMLElement"; return 1 if $type eq "HTMLOptionsCollection"; @@ -2147,7 +2152,11 @@ sub ReturnNativeToJSValue # special case for non-DOM node interfaces if (IsDOMNodeType($type)) { - return "return V8DOMWrapper::convertNodeToV8Object($value)"; + if ($signature->extendedAttributes->{"ReturnsNew"}) { + return "return V8DOMWrapper::convertNewNodeToV8Object($value)"; + } else { + return "return V8DOMWrapper::convertNodeToV8Object($value)"; + } } if ($type eq "EventTarget" or $type eq "SVGElementInstance") { @@ -2159,7 +2168,7 @@ sub ReturnNativeToJSValue } if ($type eq "EventListener") { - return "return V8DOMWrapper::convertEventListenerToV8Object($value)"; + return "return V8DOMWrapper::convertEventListenerToV8Object(imp->scriptExecutionContext(), $value)"; } if ($type eq "SerializedScriptValue") { |