diff options
Diffstat (limited to 'WebCore/bindings/js')
27 files changed, 227 insertions, 166 deletions
diff --git a/WebCore/bindings/js/GCController.cpp b/WebCore/bindings/js/GCController.cpp index d5a1789..f193b2e 100644 --- a/WebCore/bindings/js/GCController.cpp +++ b/WebCore/bindings/js/GCController.cpp @@ -61,7 +61,7 @@ GCController::GCController() void GCController::garbageCollectSoon() { if (!m_GCTimer.isActive()) - m_GCTimer.startOneShot(0.5); + m_GCTimer.startOneShot(0); } void GCController::gcTimerFired(Timer<GCController>*) diff --git a/WebCore/bindings/js/JSAttrCustom.cpp b/WebCore/bindings/js/JSAttrCustom.cpp index 4cd40ac..998ecad 100644 --- a/WebCore/bindings/js/JSAttrCustom.cpp +++ b/WebCore/bindings/js/JSAttrCustom.cpp @@ -31,9 +31,8 @@ #include "CSSHelper.h" #include "Document.h" -#include "HTMLFrameElementBase.h" +#include "Element.h" #include "HTMLNames.h" -#include "JSDOMBinding.h" using namespace JSC; @@ -41,20 +40,6 @@ namespace WebCore { using namespace HTMLNames; -void JSAttr::setValue(ExecState* exec, JSValue value) -{ - Attr* imp = static_cast<Attr*>(impl()); - String attrValue = valueToStringWithNullCheck(exec, value); - - Element* ownerElement = imp->ownerElement(); - if (ownerElement && !allowSettingSrcToJavascriptURL(exec, ownerElement, imp->name(), attrValue)) - return; - - ExceptionCode ec = 0; - imp->setValue(attrValue, ec); - setDOMException(exec, ec); -} - void JSAttr::markChildren(MarkStack& markStack) { Base::markChildren(markStack); diff --git a/WebCore/bindings/js/JSBindingsAllInOne.cpp b/WebCore/bindings/js/JSBindingsAllInOne.cpp index cd6ddfb..7a105ff 100644 --- a/WebCore/bindings/js/JSBindingsAllInOne.cpp +++ b/WebCore/bindings/js/JSBindingsAllInOne.cpp @@ -85,6 +85,7 @@ #include "JSJavaScriptCallFrameCustom.cpp" #include "JSLazyEventListener.cpp" #include "JSLocationCustom.cpp" +#include "JSMainThreadExecState.cpp" #include "JSMessageChannelConstructor.cpp" #include "JSMessageChannelCustom.cpp" #include "JSMessageEventCustom.cpp" diff --git a/WebCore/bindings/js/JSCallbackData.cpp b/WebCore/bindings/js/JSCallbackData.cpp index e128f27..e813da2 100644 --- a/WebCore/bindings/js/JSCallbackData.cpp +++ b/WebCore/bindings/js/JSCallbackData.cpp @@ -31,6 +31,7 @@ #include "Document.h" #include "JSDOMBinding.h" +#include "JSMainThreadExecState.h" using namespace JSC; @@ -59,7 +60,9 @@ JSValue JSCallbackData::invokeCallback(MarkedArgumentBuffer& args, bool* raisedE } globalObject()->globalData()->timeoutChecker.start(); - JSValue result = JSC::call(exec, function, callType, callData, callback(), args); + JSValue result = globalObject()->scriptExecutionContext()->isDocument() + ? JSMainThreadExecState::call(exec, function, callType, callData, callback(), args) + : JSC::call(exec, function, callType, callData, callback(), args); globalObject()->globalData()->timeoutChecker.stop(); Document::updateStyleForAllDocuments(); diff --git a/WebCore/bindings/js/JSDOMBinding.cpp b/WebCore/bindings/js/JSDOMBinding.cpp index a4c3d6a..87d8cf7 100644 --- a/WebCore/bindings/js/JSDOMBinding.cpp +++ b/WebCore/bindings/js/JSDOMBinding.cpp @@ -686,7 +686,7 @@ KURL completeURL(ExecState* exec, const String& relativeURL) JSValue objectToStringFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName) { - return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), 0, propertyName, objectProtoFuncToString); + return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->prototypeFunctionStructure(), 0, propertyName, objectProtoFuncToString); } Structure* getCachedDOMStructure(JSDOMGlobalObject* globalObject, const ClassInfo* classInfo) diff --git a/WebCore/bindings/js/JSDOMBinding.h b/WebCore/bindings/js/JSDOMBinding.h index 209be3f..215e09a 100644 --- a/WebCore/bindings/js/JSDOMBinding.h +++ b/WebCore/bindings/js/JSDOMBinding.h @@ -58,7 +58,10 @@ namespace WebCore { // updated to store a globalObject pointer. class DOMObjectWithGlobalPointer : public DOMObject { public: - JSDOMGlobalObject* globalObject() const { return static_cast<JSDOMGlobalObject*>(getAnonymousValue(GlobalObjectSlot).asCell()); } + JSDOMGlobalObject* globalObject() const + { + return static_cast<JSDOMGlobalObject*>(DOMObject::globalObject()); + } ScriptExecutionContext* scriptExecutionContext() const { @@ -72,19 +75,14 @@ namespace WebCore { } protected: - static const unsigned AnonymousSlotCount = 1 + DOMObject::AnonymousSlotCount; - static const unsigned GlobalObjectSlot = AnonymousSlotCount - 1; - DOMObjectWithGlobalPointer(NonNullPassRefPtr<JSC::Structure> structure, JSDOMGlobalObject* globalObject) - : DOMObject(structure) + : DOMObject(globalObject, structure) { // FIXME: This ASSERT is valid, but fires in fast/dom/gc-6.html when trying to create // new JavaScript objects on detached windows due to DOMWindow::document() // needing to reach through the frame to get to the Document*. See bug 27640. // ASSERT(globalObject->scriptExecutionContext()); - putAnonymousValue(GlobalObjectSlot, globalObject); } - virtual ~DOMObjectWithGlobalPointer() { } }; // Base class for all constructor objects in the JSC bindings. diff --git a/WebCore/bindings/js/JSDOMWindowCustom.cpp b/WebCore/bindings/js/JSDOMWindowCustom.cpp index 656d580..343c8f9 100644 --- a/WebCore/bindings/js/JSDOMWindowCustom.cpp +++ b/WebCore/bindings/js/JSDOMWindowCustom.cpp @@ -130,7 +130,7 @@ void JSDOMWindow::markChildren(MarkStack& markStack) template<NativeFunction nativeFunction, int length> JSValue nonCachingStaticFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName) { - return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), length, propertyName, nativeFunction); + return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->prototypeFunctionStructure(), length, propertyName, nativeFunction); } static JSValue childFrameGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName) diff --git a/WebCore/bindings/js/JSDOMWindowShell.cpp b/WebCore/bindings/js/JSDOMWindowShell.cpp index 1e82a49..65096b9 100644 --- a/WebCore/bindings/js/JSDOMWindowShell.cpp +++ b/WebCore/bindings/js/JSDOMWindowShell.cpp @@ -61,10 +61,11 @@ void JSDOMWindowShell::setWindow(PassRefPtr<DOMWindow> domWindow) // when we allocate the global object. (Once the global object is fully // constructed, it can mark its own prototype.) RefPtr<Structure> prototypeStructure = JSDOMWindowPrototype::createStructure(jsNull()); - ProtectedPtr<JSDOMWindowPrototype> prototype = new JSDOMWindowPrototype(prototypeStructure.release()); + ProtectedPtr<JSDOMWindowPrototype> prototype = new JSDOMWindowPrototype(0, prototypeStructure.release()); RefPtr<Structure> structure = JSDOMWindow::createStructure(prototype); JSDOMWindow* jsDOMWindow = new (JSDOMWindow::commonJSGlobalData()) JSDOMWindow(structure.release(), domWindow, this); + prototype->putAnonymousValue(0, jsDOMWindow); setWindow(jsDOMWindow); } diff --git a/WebCore/bindings/js/JSDOMWindowShell.h b/WebCore/bindings/js/JSDOMWindowShell.h index 1b986b8..888325d 100644 --- a/WebCore/bindings/js/JSDOMWindowShell.h +++ b/WebCore/bindings/js/JSDOMWindowShell.h @@ -37,8 +37,8 @@ namespace WebCore { class DOMWindow; class Frame; - class JSDOMWindowShell : public DOMObject { - typedef DOMObject Base; + class JSDOMWindowShell : public JSC::JSObject { + typedef JSC::JSObject Base; public: JSDOMWindowShell(PassRefPtr<DOMWindow>, DOMWrapperWorld* world); virtual ~JSDOMWindowShell(); @@ -66,7 +66,7 @@ namespace WebCore { DOMWrapperWorld* world() { return m_world.get(); } private: - static const unsigned StructureFlags = JSC::OverridesGetOwnPropertySlot | JSC::OverridesMarkChildren | JSC::OverridesGetPropertyNames | DOMObject::StructureFlags; + static const unsigned StructureFlags = JSC::OverridesGetOwnPropertySlot | JSC::OverridesMarkChildren | JSC::OverridesGetPropertyNames | Base::StructureFlags; virtual void markChildren(JSC::MarkStack&); virtual JSC::UString className() const; diff --git a/WebCore/bindings/js/JSDOMWrapper.h b/WebCore/bindings/js/JSDOMWrapper.h index 00594cf..2d09f01 100644 --- a/WebCore/bindings/js/JSDOMWrapper.h +++ b/WebCore/bindings/js/JSDOMWrapper.h @@ -22,15 +22,15 @@ #ifndef JSDOMWrapper_h #define JSDOMWrapper_h -#include <runtime/JSObject.h> +#include <runtime/JSObjectWithGlobalObject.h> namespace WebCore { -// Base class for all objects in this binding except Window. -class DOMObject : public JSC::JSObject { +// FIXME: Rename to JSDOMWrapper. +class DOMObject : public JSC::JSObjectWithGlobalObject { protected: - explicit DOMObject(NonNullPassRefPtr<JSC::Structure> structure) - : JSObject(structure) + explicit DOMObject(JSC::JSGlobalObject* globalObject, NonNullPassRefPtr<JSC::Structure> structure) + : JSObjectWithGlobalObject(globalObject, structure) { } diff --git a/WebCore/bindings/js/JSEventCustom.cpp b/WebCore/bindings/js/JSEventCustom.cpp index e5fdbe7..bc69323 100644 --- a/WebCore/bindings/js/JSEventCustom.cpp +++ b/WebCore/bindings/js/JSEventCustom.cpp @@ -32,11 +32,13 @@ #include "Clipboard.h" #include "CompositionEvent.h" #include "CustomEvent.h" +#include "DeviceOrientationEvent.h" #include "Event.h" #include "JSBeforeLoadEvent.h" #include "JSClipboard.h" #include "JSCustomEvent.h" #include "JSCompositionEvent.h" +#include "JSDeviceOrientationEvent.h" #include "JSErrorEvent.h" #if ENABLE(INDEXED_DATABASE) #include "JSIDBErrorEvent.h" @@ -171,6 +173,10 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, Event* event) wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, PopStateEvent, event); else if (event->isCustomEvent()) wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, CustomEvent, event); +#if ENABLE(DEVICE_ORIENTATION) + else if (event->isDeviceOrientationEvent()) + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, DeviceOrientationEvent, event); +#endif else wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, Event, event); diff --git a/WebCore/bindings/js/JSEventListener.cpp b/WebCore/bindings/js/JSEventListener.cpp index c64aa29..e25a5d1 100644 --- a/WebCore/bindings/js/JSEventListener.cpp +++ b/WebCore/bindings/js/JSEventListener.cpp @@ -24,6 +24,7 @@ #include "Frame.h" #include "JSEvent.h" #include "JSEventTarget.h" +#include "JSMainThreadExecState.h" #include <runtime/JSLock.h> #include <wtf/RefCountedLeakCounter.h> @@ -111,9 +112,17 @@ void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext DynamicGlobalObjectScope globalObjectScope(exec, globalData->dynamicGlobalObject ? globalData->dynamicGlobalObject : globalObject); globalData->timeoutChecker.start(); - JSValue retval = handleEventFunction - ? JSC::call(exec, handleEventFunction, callType, callData, jsFunction, args) - : JSC::call(exec, jsFunction, callType, callData, toJS(exec, globalObject, event->currentTarget()), args); + JSValue retval; + if (handleEventFunction) { + retval = scriptExecutionContext->isDocument() + ? JSMainThreadExecState::call(exec, handleEventFunction, callType, callData, jsFunction, args) + : JSC::call(exec, handleEventFunction, callType, callData, jsFunction, args); + } else { + JSValue currentTarget = toJS(exec, globalObject, event->currentTarget()); + retval = scriptExecutionContext->isDocument() + ? JSMainThreadExecState::call(exec, jsFunction, callType, callData, currentTarget, args) + : JSC::call(exec, jsFunction, callType, callData, currentTarget, args); + } globalData->timeoutChecker.stop(); globalObject->setCurrentEvent(savedEvent); diff --git a/WebCore/bindings/js/JSHistoryCustom.cpp b/WebCore/bindings/js/JSHistoryCustom.cpp index c031b30..53b554f 100644 --- a/WebCore/bindings/js/JSHistoryCustom.cpp +++ b/WebCore/bindings/js/JSHistoryCustom.cpp @@ -40,17 +40,17 @@ namespace WebCore { static JSValue nonCachingStaticBackFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName) { - return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), 0, propertyName, jsHistoryPrototypeFunctionBack); + return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->prototypeFunctionStructure(), 0, propertyName, jsHistoryPrototypeFunctionBack); } static JSValue nonCachingStaticForwardFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName) { - return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), 0, propertyName, jsHistoryPrototypeFunctionForward); + return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->prototypeFunctionStructure(), 0, propertyName, jsHistoryPrototypeFunctionForward); } static JSValue nonCachingStaticGoFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName) { - return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), 1, propertyName, jsHistoryPrototypeFunctionGo); + return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->prototypeFunctionStructure(), 1, propertyName, jsHistoryPrototypeFunctionGo); } bool JSHistory::getOwnPropertySlotDelegate(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) diff --git a/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp b/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp index 1fedd7e..df191b7 100644 --- a/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp +++ b/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp @@ -36,6 +36,7 @@ #if ENABLE(INSPECTOR) #include "Console.h" +#include "JSMainThreadExecState.h" #if ENABLE(DATABASE) #include "Database.h" #include "JSDatabase.h" @@ -82,7 +83,7 @@ ScriptObject InjectedScriptHost::createInjectedScript(const String& source, Scri JSLock lock(SilenceAssertionsOnly); JSDOMGlobalObject* globalObject = static_cast<JSDOMGlobalObject*>(scriptState->lexicalGlobalObject()); JSValue globalThisValue = scriptState->globalThisValue(); - Completion comp = JSC::evaluate(scriptState, globalObject->globalScopeChain(), sourceCode, globalThisValue); + Completion comp = JSMainThreadExecState::evaluate(scriptState, globalObject->globalScopeChain(), sourceCode, globalThisValue); if (comp.complType() != JSC::Normal && comp.complType() != JSC::ReturnValue) return ScriptObject(); JSValue functionValue = comp.value(); diff --git a/WebCore/bindings/js/JSLocationCustom.cpp b/WebCore/bindings/js/JSLocationCustom.cpp index e92a750..da35c23 100644 --- a/WebCore/bindings/js/JSLocationCustom.cpp +++ b/WebCore/bindings/js/JSLocationCustom.cpp @@ -41,17 +41,17 @@ namespace WebCore { static JSValue nonCachingStaticReplaceFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName) { - return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), 1, propertyName, jsLocationPrototypeFunctionReplace); + return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->prototypeFunctionStructure(), 1, propertyName, jsLocationPrototypeFunctionReplace); } static JSValue nonCachingStaticReloadFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName) { - return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), 0, propertyName, jsLocationPrototypeFunctionReload); + return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->prototypeFunctionStructure(), 0, propertyName, jsLocationPrototypeFunctionReload); } static JSValue nonCachingStaticAssignFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName) { - return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), 1, propertyName, jsLocationPrototypeFunctionAssign); + return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->prototypeFunctionStructure(), 1, propertyName, jsLocationPrototypeFunctionAssign); } bool JSLocation::getOwnPropertySlotDelegate(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) diff --git a/WebCore/bindings/js/JSMainThreadExecState.cpp b/WebCore/bindings/js/JSMainThreadExecState.cpp new file mode 100644 index 0000000..d679a58 --- /dev/null +++ b/WebCore/bindings/js/JSMainThreadExecState.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 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. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS 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 "JSMainThreadExecState.h" + +namespace WebCore { + +JSC::ExecState* JSMainThreadExecState::s_mainThreadState = 0; + +} // namespace WebCore diff --git a/WebCore/bindings/js/JSMainThreadExecState.h b/WebCore/bindings/js/JSMainThreadExecState.h new file mode 100644 index 0000000..8193d7c --- /dev/null +++ b/WebCore/bindings/js/JSMainThreadExecState.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 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. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS 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 JSMainThreadExecState_h +#define JSMainThreadExecState_h + +#include <JSDOMBinding.h> +#ifndef NDEBUG +#include <wtf/MainThread.h> +#endif +#include <wtf/Noncopyable.h> + +namespace WebCore { + +class JSMainThreadExecState : public Noncopyable { +public: + static JSC::ExecState* currentState() + { + ASSERT(WTF::isMainThread()); + return s_mainThreadState; + }; + + static JSC::JSValue call(JSC::ExecState* exec, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData& callData, JSC::JSValue thisValue, const JSC::ArgList& args) + { + JSMainThreadExecState currentState(exec); + return JSC::call(exec, functionObject, callType, callData, thisValue, args); + }; + + static JSC::Completion evaluate(JSC::ExecState* exec, JSC::ScopeChain& chain, const JSC::SourceCode& source, JSC::JSValue thisValue) + { + JSMainThreadExecState currentState(exec); + return JSC::evaluate(exec, chain, source, thisValue); + }; + +protected: + explicit JSMainThreadExecState(JSC::ExecState* exec) + : m_previousState(s_mainThreadState) + { + ASSERT(WTF::isMainThread()); + s_mainThreadState = exec; + }; + + ~JSMainThreadExecState() + { + ASSERT(WTF::isMainThread()); + s_mainThreadState = m_previousState; + } + +private: + static JSC::ExecState* s_mainThreadState; + JSC::ExecState* m_previousState; +}; + +// Null state prevents origin security checks. +class JSMainThreadNullState : private JSMainThreadExecState { +public: + explicit JSMainThreadNullState() : JSMainThreadExecState(0) {}; +}; + +} // namespace WebCore + +#endif // JSMainThreadExecState_h diff --git a/WebCore/bindings/js/JSNamedNodeMapCustom.cpp b/WebCore/bindings/js/JSNamedNodeMapCustom.cpp index e1c490e..8df9304 100644 --- a/WebCore/bindings/js/JSNamedNodeMapCustom.cpp +++ b/WebCore/bindings/js/JSNamedNodeMapCustom.cpp @@ -35,38 +35,6 @@ using namespace JSC; namespace WebCore { -JSValue JSNamedNodeMap::setNamedItem(ExecState* exec, const ArgList& args) -{ - NamedNodeMap* imp = static_cast<NamedNodeMap*>(impl()); - ExceptionCode ec = 0; - Node* newNode = toNode(args.at(0)); - - if (newNode && newNode->nodeType() == Node::ATTRIBUTE_NODE && imp->element()) { - if (!allowSettingSrcToJavascriptURL(exec, imp->element(), newNode->nodeName(), newNode->nodeValue())) - return jsNull(); - } - - JSValue result = toJS(exec, globalObject(), WTF::getPtr(imp->setNamedItem(newNode, ec))); - setDOMException(exec, ec); - return result; -} - -JSValue JSNamedNodeMap::setNamedItemNS(ExecState* exec, const ArgList& args) -{ - NamedNodeMap* imp = static_cast<NamedNodeMap*>(impl()); - ExceptionCode ec = 0; - Node* newNode = toNode(args.at(0)); - - if (newNode && newNode->nodeType() == Node::ATTRIBUTE_NODE && imp->element()) { - if (!allowSettingSrcToJavascriptURL(exec, imp->element(), newNode->nodeName(), newNode->nodeValue())) - return jsNull(); - } - - JSValue result = toJS(exec, globalObject(), WTF::getPtr(imp->setNamedItemNS(newNode, ec))); - setDOMException(exec, ec); - return result; -} - bool JSNamedNodeMap::canGetItemsForName(ExecState*, NamedNodeMap* impl, const Identifier& propertyName) { return impl->getNamedItem(identifierToString(propertyName)); diff --git a/WebCore/bindings/js/JSNodeCustom.cpp b/WebCore/bindings/js/JSNodeCustom.cpp index 9fbcffd..747f238 100644 --- a/WebCore/bindings/js/JSNodeCustom.cpp +++ b/WebCore/bindings/js/JSNodeCustom.cpp @@ -68,51 +68,9 @@ using namespace JSC; namespace WebCore { -static inline bool isAttrFrameSrc(Element *element, const String& name) -{ - return element && (element->hasTagName(HTMLNames::iframeTag) || element->hasTagName(HTMLNames::frameTag)) && equalIgnoringCase(name, "src"); -} - -void JSNode::setNodeValue(JSC::ExecState* exec, JSC::JSValue value) -{ - Node* imp = static_cast<Node*>(impl()); - String nodeValue = valueToStringWithNullCheck(exec, value); - - if (imp->nodeType() == Node::ATTRIBUTE_NODE) { - Element* ownerElement = static_cast<Attr*>(impl())->ownerElement(); - if (ownerElement && !allowSettingSrcToJavascriptURL(exec, ownerElement, imp->nodeName(), nodeValue)) - return; - } - - ExceptionCode ec = 0; - imp->setNodeValue(nodeValue, ec); - setDOMException(exec, ec); -} - -void JSNode::setTextContent(JSC::ExecState* exec, JSC::JSValue value) -{ - Node* imp = static_cast<Node*>(impl()); - String nodeValue = valueToStringWithNullCheck(exec, value); - - if (imp->nodeType() == Node::ATTRIBUTE_NODE) { - Element* ownerElement = static_cast<Attr*>(impl())->ownerElement(); - if (ownerElement && !allowSettingSrcToJavascriptURL(exec, ownerElement, imp->nodeName(), nodeValue)) - return; - } - - ExceptionCode ec = 0; - imp->setTextContent(nodeValue, ec); - setDOMException(exec, ec); -} - JSValue JSNode::insertBefore(ExecState* exec, const ArgList& args) { Node* imp = static_cast<Node*>(impl()); - if (imp->nodeType() == Node::ATTRIBUTE_NODE && isAttrFrameSrc(static_cast<Attr*>(impl())->ownerElement(), imp->nodeName())) { - setDOMException(exec, NOT_SUPPORTED_ERR); - return jsNull(); - } - ExceptionCode ec = 0; bool ok = imp->insertBefore(toNode(args.at(0)), toNode(args.at(1)), ec, true); setDOMException(exec, ec); @@ -124,11 +82,6 @@ JSValue JSNode::insertBefore(ExecState* exec, const ArgList& args) JSValue JSNode::replaceChild(ExecState* exec, const ArgList& args) { Node* imp = static_cast<Node*>(impl()); - if (imp->nodeType() == Node::ATTRIBUTE_NODE && isAttrFrameSrc(static_cast<Attr*>(impl())->ownerElement(), imp->nodeName())) { - setDOMException(exec, NOT_SUPPORTED_ERR); - return jsNull(); - } - ExceptionCode ec = 0; bool ok = imp->replaceChild(toNode(args.at(0)), toNode(args.at(1)), ec, true); setDOMException(exec, ec); @@ -140,11 +93,6 @@ JSValue JSNode::replaceChild(ExecState* exec, const ArgList& args) JSValue JSNode::removeChild(ExecState* exec, const ArgList& args) { Node* imp = static_cast<Node*>(impl()); - if (imp->nodeType() == Node::ATTRIBUTE_NODE && isAttrFrameSrc(static_cast<Attr*>(impl())->ownerElement(), imp->nodeName())) { - setDOMException(exec, NOT_SUPPORTED_ERR); - return jsNull(); - } - ExceptionCode ec = 0; bool ok = imp->removeChild(toNode(args.at(0)), ec); setDOMException(exec, ec); @@ -156,11 +104,6 @@ JSValue JSNode::removeChild(ExecState* exec, const ArgList& args) JSValue JSNode::appendChild(ExecState* exec, const ArgList& args) { Node* imp = static_cast<Node*>(impl()); - if (imp->nodeType() == Node::ATTRIBUTE_NODE && isAttrFrameSrc(static_cast<Attr*>(impl())->ownerElement(), imp->nodeName())) { - setDOMException(exec, NOT_SUPPORTED_ERR); - return jsNull(); - } - ExceptionCode ec = 0; bool ok = imp->appendChild(toNode(args.at(0)), ec, true); setDOMException(exec, ec); diff --git a/WebCore/bindings/js/ScheduledAction.cpp b/WebCore/bindings/js/ScheduledAction.cpp index 8fc860b..8cafefe 100644 --- a/WebCore/bindings/js/ScheduledAction.cpp +++ b/WebCore/bindings/js/ScheduledAction.cpp @@ -30,6 +30,7 @@ #include "FrameLoader.h" #include "JSDOMBinding.h" #include "JSDOMWindow.h" +#include "JSMainThreadExecState.h" #include "ScriptController.h" #include "ScriptExecutionContext.h" #include "ScriptSourceCode.h" @@ -84,7 +85,7 @@ void ScheduledAction::execute(ScriptExecutionContext* context) #endif } -void ScheduledAction::executeFunctionInContext(JSGlobalObject* globalObject, JSValue thisValue) +void ScheduledAction::executeFunctionInContext(JSGlobalObject* globalObject, JSValue thisValue, ScriptExecutionContext* context) { ASSERT(m_function); JSLock lock(SilenceAssertionsOnly); @@ -102,7 +103,10 @@ void ScheduledAction::executeFunctionInContext(JSGlobalObject* globalObject, JSV args.append(m_args[i]); globalObject->globalData()->timeoutChecker.start(); - JSC::call(exec, m_function, callType, callData, thisValue, args); + if (context->isDocument()) + JSMainThreadExecState::call(exec, m_function, callType, callData, thisValue, args); + else + JSC::call(exec, m_function, callType, callData, thisValue, args); globalObject->globalData()->timeoutChecker.stop(); if (exec->hadException()) @@ -122,7 +126,7 @@ void ScheduledAction::execute(Document* document) frame->script()->setProcessingTimerCallback(true); if (m_function) { - executeFunctionInContext(window, window->shell()); + executeFunctionInContext(window, window->shell(), document); Document::updateStyleForAllDocuments(); } else frame->script()->executeScriptInWorld(m_isolatedWorld.get(), m_code); @@ -140,7 +144,7 @@ void ScheduledAction::execute(WorkerContext* workerContext) if (m_function) { JSWorkerContext* contextWrapper = scriptController->workerContextWrapper(); - executeFunctionInContext(contextWrapper, contextWrapper); + executeFunctionInContext(contextWrapper, contextWrapper, workerContext); } else { ScriptSourceCode code(m_code, workerContext->url()); scriptController->evaluate(code); diff --git a/WebCore/bindings/js/ScheduledAction.h b/WebCore/bindings/js/ScheduledAction.h index 3b7e001..313451a 100644 --- a/WebCore/bindings/js/ScheduledAction.h +++ b/WebCore/bindings/js/ScheduledAction.h @@ -55,7 +55,7 @@ namespace WebCore { { } - void executeFunctionInContext(JSC::JSGlobalObject*, JSC::JSValue thisValue); + void executeFunctionInContext(JSC::JSGlobalObject*, JSC::JSValue thisValue, ScriptExecutionContext*); void execute(Document*); #if ENABLE(WORKERS) void execute(WorkerContext*); diff --git a/WebCore/bindings/js/ScriptCallStack.cpp b/WebCore/bindings/js/ScriptCallStack.cpp index 771141d..64600cf 100644 --- a/WebCore/bindings/js/ScriptCallStack.cpp +++ b/WebCore/bindings/js/ScriptCallStack.cpp @@ -33,7 +33,7 @@ #include <interpreter/CallFrame.h> #include <interpreter/Interpreter.h> -#include <runtime/InternalFunction.h> +#include <runtime/JSFunction.h> #include <runtime/JSValue.h> #include <runtime/UString.h> #include <runtime/JSGlobalData.h> @@ -57,7 +57,7 @@ ScriptCallStack::ScriptCallStack(ExecState* exec, const ArgList& args, unsigned unsigned lineNumber = signedLineNumber >= 0 ? signedLineNumber : 0; if (function) { - m_caller = asInternalFunction(function); + m_caller = asFunction(function); m_frames.append(ScriptCallFrame(m_caller->name(m_exec), urlString, lineNumber, args, skipArgumentCount)); } else { // Caller is unknown, but we should still add the frame, because @@ -93,10 +93,10 @@ void ScriptCallStack::initialize() JSValue func = m_exec->interpreter()->retrieveCaller(m_exec, m_caller); while (!func.isNull()) { - InternalFunction* internalFunction = asInternalFunction(func); + JSFunction* jsFunction = asFunction(func); ArgList emptyArgList; - m_frames.append(ScriptCallFrame(internalFunction->name(m_exec), UString(), 0, emptyArgList, 0)); - func = m_exec->interpreter()->retrieveCaller(m_exec, internalFunction); + m_frames.append(ScriptCallFrame(jsFunction->name(m_exec), UString(), 0, emptyArgList, 0)); + func = m_exec->interpreter()->retrieveCaller(m_exec, jsFunction); } m_initialized = true; } diff --git a/WebCore/bindings/js/ScriptCallStack.h b/WebCore/bindings/js/ScriptCallStack.h index e51d97a..7b66a97 100644 --- a/WebCore/bindings/js/ScriptCallStack.h +++ b/WebCore/bindings/js/ScriptCallStack.h @@ -61,7 +61,7 @@ namespace WebCore { JSC::ExecState* m_exec; Vector<ScriptCallFrame> m_frames; - JSC::InternalFunction* m_caller; + JSC::JSFunction* m_caller; }; } // namespace WebCore diff --git a/WebCore/bindings/js/ScriptController.cpp b/WebCore/bindings/js/ScriptController.cpp index 508b2f8..3dcbb0b 100644 --- a/WebCore/bindings/js/ScriptController.cpp +++ b/WebCore/bindings/js/ScriptController.cpp @@ -29,6 +29,7 @@ #include "HTMLPlugInElement.h" #include "InspectorTimelineAgent.h" #include "JSDocument.h" +#include "JSMainThreadExecState.h" #include "NP_jsobject.h" #include "Page.h" #include "PageGroup.h" @@ -110,12 +111,12 @@ JSDOMWindowShell* ScriptController::createWindowShell(DOMWrapperWorld* world) return windowShell; } -ScriptValue ScriptController::evaluateInWorld(const ScriptSourceCode& sourceCode, DOMWrapperWorld* world) +ScriptValue ScriptController::evaluateInWorld(const ScriptSourceCode& sourceCode, DOMWrapperWorld* world, ShouldAllowXSS shouldAllowXSS) { const SourceCode& jsSourceCode = sourceCode.jsSourceCode(); String sourceURL = ustringToString(jsSourceCode.provider()->url()); - if (!m_XSSAuditor->canEvaluate(sourceCode.source())) { + if (shouldAllowXSS == DoNotAllowXSS && !m_XSSAuditor->canEvaluate(sourceCode.source())) { // This script is not safe to be evaluated. return JSValue(); } @@ -142,7 +143,7 @@ ScriptValue ScriptController::evaluateInWorld(const ScriptSourceCode& sourceCode #endif exec->globalData().timeoutChecker.start(); - Completion comp = JSC::evaluate(exec, exec->dynamicGlobalObject()->globalScopeChain(), jsSourceCode, shell); + Completion comp = JSMainThreadExecState::evaluate(exec, exec->dynamicGlobalObject()->globalScopeChain(), jsSourceCode, shell); exec->globalData().timeoutChecker.stop(); #if ENABLE(INSPECTOR) @@ -166,9 +167,9 @@ ScriptValue ScriptController::evaluateInWorld(const ScriptSourceCode& sourceCode return JSValue(); } -ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode) +ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode, ShouldAllowXSS shouldAllowXSS) { - return evaluateInWorld(sourceCode, mainThreadNormalWorld()); + return evaluateInWorld(sourceCode, mainThreadNormalWorld(), shouldAllowXSS); } PassRefPtr<DOMWrapperWorld> ScriptController::createWorld() @@ -181,7 +182,7 @@ void ScriptController::getAllWorlds(Vector<DOMWrapperWorld*>& worlds) static_cast<WebCoreJSClientData*>(JSDOMWindow::commonJSGlobalData()->clientData)->getAllWorlds(worlds); } -void ScriptController::clearWindowShell() +void ScriptController::clearWindowShell(bool goingIntoPageCache) { if (m_windowShells.isEmpty()) return; @@ -203,8 +204,10 @@ void ScriptController::clearWindowShell() } } - // It's likely that resetting our windows created a lot of garbage. - gcController().garbageCollectSoon(); + // It's likely that resetting our windows created a lot of garbage, unless + // it went in a back/forward cache. + if (!goingIntoPageCache) + gcController().garbageCollectSoon(); } JSDOMWindowShell* ScriptController::initScript(DOMWrapperWorld* world) @@ -283,6 +286,16 @@ bool ScriptController::anyPageIsProcessingUserGesture() const return false; } +bool ScriptController::canAccessFromCurrentOrigin(Frame *frame) +{ + ExecState* exec = JSMainThreadExecState::currentState(); + if (exec) + return allowsAccessFromFrame(exec, frame); + // If the current state is 0 we're in a call path where the DOM security + // check doesn't apply (eg. parser). + return true; +} + void ScriptController::attachDebugger(JSC::Debugger* debugger) { for (ShellMap::iterator iter = m_windowShells.begin(); iter != m_windowShells.end(); ++iter) @@ -441,7 +454,7 @@ void ScriptController::clearScriptObjects() #endif } -ScriptValue ScriptController::executeScriptInWorld(DOMWrapperWorld* world, const String& script, bool forceUserGesture) +ScriptValue ScriptController::executeScriptInWorld(DOMWrapperWorld* world, const String& script, bool forceUserGesture, ShouldAllowXSS shouldAllowXSS) { ScriptSourceCode sourceCode(script, forceUserGesture ? KURL() : m_frame->loader()->url()); @@ -451,7 +464,7 @@ ScriptValue ScriptController::executeScriptInWorld(DOMWrapperWorld* world, const bool wasInExecuteScript = m_inExecuteScript; m_inExecuteScript = true; - ScriptValue result = evaluateInWorld(sourceCode, world); + ScriptValue result = evaluateInWorld(sourceCode, world, shouldAllowXSS); if (!wasInExecuteScript) { m_inExecuteScript = false; diff --git a/WebCore/bindings/js/ScriptController.h b/WebCore/bindings/js/ScriptController.h index ed6c0a0..877eb9f 100644 --- a/WebCore/bindings/js/ScriptController.h +++ b/WebCore/bindings/js/ScriptController.h @@ -67,6 +67,12 @@ enum ReasonForCallingCanExecuteScripts { NotAboutToExecuteScript }; +// Whether to call the XSSAuditor to audit a script before passing it to the JavaScript engine. +enum ShouldAllowXSS { + AllowXSS, + DoNotAllowXSS +}; + class ScriptController { friend class ScriptCachedFrameData; typedef WTF::HashMap< RefPtr<DOMWrapperWorld>, JSC::ProtectedPtr<JSDOMWindowShell> > ShellMap; @@ -97,9 +103,9 @@ public: static void getAllWorlds(Vector<DOMWrapperWorld*>&); - ScriptValue executeScript(const ScriptSourceCode&); - ScriptValue executeScript(const String& script, bool forceUserGesture = false); - ScriptValue executeScriptInWorld(DOMWrapperWorld* world, const String& script, bool forceUserGesture = false); + ScriptValue executeScript(const ScriptSourceCode&, ShouldAllowXSS shouldAllowXSS = DoNotAllowXSS); + ScriptValue executeScript(const String& script, bool forceUserGesture = false, ShouldAllowXSS shouldAllowXSS = DoNotAllowXSS); + ScriptValue executeScriptInWorld(DOMWrapperWorld* world, const String& script, bool forceUserGesture = false, ShouldAllowXSS shouldAllowXSS = DoNotAllowXSS); // Returns true if argument is a JavaScript URL. bool executeIfJavaScriptURL(const KURL&, bool userGesture = false, ShouldReplaceDocumentIfJavaScriptURL shouldReplaceDocumentIfJavaScriptURL = ReplaceDocumentIfJavaScriptURL); @@ -108,8 +114,8 @@ public: // 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&); - ScriptValue evaluateInWorld(const ScriptSourceCode&, DOMWrapperWorld*); + ScriptValue evaluate(const ScriptSourceCode&, ShouldAllowXSS shouldAllowXSS = DoNotAllowXSS); + ScriptValue evaluateInWorld(const ScriptSourceCode&, DOMWrapperWorld*, ShouldAllowXSS shouldAllowXSS = DoNotAllowXSS); void setEventHandlerLineNumber(int lineno) { m_handlerLineNumber = lineno; } int eventHandlerLineNumber() { return m_handlerLineNumber; } @@ -118,6 +124,7 @@ public: bool processingUserGesture(DOMWrapperWorld*) const; bool anyPageIsProcessingUserGesture() const; + static bool canAccessFromCurrentOrigin(Frame*); bool canExecuteScripts(ReasonForCallingCanExecuteScripts); // Debugger can be 0 to detach any existing Debugger. @@ -132,7 +139,7 @@ public: const String* sourceURL() const { return m_sourceURL; } // 0 if we are not evaluating any script - void clearWindowShell(); + void clearWindowShell(bool goingIntoPageCache = false); void updateDocument(); // Notifies the ScriptController that the securityOrigin of the current diff --git a/WebCore/bindings/js/ScriptFunctionCall.cpp b/WebCore/bindings/js/ScriptFunctionCall.cpp index e9073b5..3784457 100644 --- a/WebCore/bindings/js/ScriptFunctionCall.cpp +++ b/WebCore/bindings/js/ScriptFunctionCall.cpp @@ -32,6 +32,7 @@ #include "ScriptFunctionCall.h" #include "JSDOMBinding.h" +#include "JSMainThreadExecState.h" #include "ScriptString.h" #include "ScriptValue.h" @@ -146,7 +147,7 @@ ScriptValue ScriptFunctionCall::call(bool& hadException, bool reportExceptions) if (callType == CallTypeNone) return ScriptValue(); - JSValue result = JSC::call(m_exec, function, callType, callData, thisObject, m_arguments); + JSValue result = JSMainThreadExecState::call(m_exec, function, callType, callData, thisObject, m_arguments); if (m_exec->hadException()) { if (reportExceptions) reportException(m_exec, m_exec->exception()); diff --git a/WebCore/bindings/js/WorkerScriptController.cpp b/WebCore/bindings/js/WorkerScriptController.cpp index 85d6861..1d45dfa 100644 --- a/WebCore/bindings/js/WorkerScriptController.cpp +++ b/WebCore/bindings/js/WorkerScriptController.cpp @@ -71,22 +71,26 @@ void WorkerScriptController::initScript() // when we allocate the global object. (Once the global object is fully // constructed, it can mark its own prototype.) RefPtr<Structure> workerContextPrototypeStructure = JSWorkerContextPrototype::createStructure(jsNull()); - ProtectedPtr<JSWorkerContextPrototype> workerContextPrototype = new (m_globalData.get()) JSWorkerContextPrototype(workerContextPrototypeStructure.release()); + ProtectedPtr<JSWorkerContextPrototype> workerContextPrototype = new (m_globalData.get()) JSWorkerContextPrototype(0, workerContextPrototypeStructure.release()); if (m_workerContext->isDedicatedWorkerContext()) { RefPtr<Structure> dedicatedContextPrototypeStructure = JSDedicatedWorkerContextPrototype::createStructure(workerContextPrototype); - ProtectedPtr<JSDedicatedWorkerContextPrototype> dedicatedContextPrototype = new (m_globalData.get()) JSDedicatedWorkerContextPrototype(dedicatedContextPrototypeStructure.release()); + ProtectedPtr<JSDedicatedWorkerContextPrototype> dedicatedContextPrototype = new (m_globalData.get()) JSDedicatedWorkerContextPrototype(0, dedicatedContextPrototypeStructure.release()); RefPtr<Structure> structure = JSDedicatedWorkerContext::createStructure(dedicatedContextPrototype); m_workerContextWrapper = new (m_globalData.get()) JSDedicatedWorkerContext(structure.release(), m_workerContext->toDedicatedWorkerContext()); + workerContextPrototype->putAnonymousValue(0, m_workerContextWrapper); + dedicatedContextPrototype->putAnonymousValue(0, m_workerContextWrapper); #if ENABLE(SHARED_WORKERS) } else { ASSERT(m_workerContext->isSharedWorkerContext()); RefPtr<Structure> sharedContextPrototypeStructure = JSSharedWorkerContextPrototype::createStructure(workerContextPrototype); - ProtectedPtr<JSSharedWorkerContextPrototype> sharedContextPrototype = new (m_globalData.get()) JSSharedWorkerContextPrototype(sharedContextPrototypeStructure.release()); + ProtectedPtr<JSSharedWorkerContextPrototype> sharedContextPrototype = new (m_globalData.get()) JSSharedWorkerContextPrototype(0, sharedContextPrototypeStructure.release()); RefPtr<Structure> structure = JSSharedWorkerContext::createStructure(sharedContextPrototype); m_workerContextWrapper = new (m_globalData.get()) JSSharedWorkerContext(structure.release(), m_workerContext->toSharedWorkerContext()); + workerContextPrototype->putAnonymousValue(0, m_workerContextWrapper); + sharedContextPrototype->putAnonymousValue(0, m_workerContextWrapper); #endif } } |