diff options
Diffstat (limited to 'WebCore/bindings/js')
135 files changed, 2912 insertions, 1338 deletions
diff --git a/WebCore/bindings/js/CachedScriptSourceProvider.h b/WebCore/bindings/js/CachedScriptSourceProvider.h index 1cdd8aa..8e69b6b 100644 --- a/WebCore/bindings/js/CachedScriptSourceProvider.h +++ b/WebCore/bindings/js/CachedScriptSourceProvider.h @@ -50,7 +50,7 @@ namespace WebCore { private: CachedScriptSourceProvider(CachedScript* cachedScript) - : ScriptSourceProvider(cachedScript->url()) + : ScriptSourceProvider(stringToUString(cachedScript->url())) , m_cachedScript(cachedScript) { m_cachedScript->addClient(this); diff --git a/WebCore/bindings/js/DOMObjectHashTableMap.cpp b/WebCore/bindings/js/DOMObjectHashTableMap.cpp new file mode 100644 index 0000000..bfcab0b --- /dev/null +++ b/WebCore/bindings/js/DOMObjectHashTableMap.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2007 Samuel Weinig <sam@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "DOMObjectHashTableMap.h" + +#include "WebCoreJSClientData.h" + +using namespace JSC; + +namespace WebCore{ + +DOMObjectHashTableMap& DOMObjectHashTableMap::mapFor(JSGlobalData& globalData) +{ + JSGlobalData::ClientData* clientData = globalData.clientData; + ASSERT(clientData); + return static_cast<WebCoreJSClientData*>(clientData)->hashTableMap; +} + +} // namespace WebCore diff --git a/WebCore/bindings/js/DOMObjectHashTableMap.h b/WebCore/bindings/js/DOMObjectHashTableMap.h new file mode 100644 index 0000000..4ddacb8 --- /dev/null +++ b/WebCore/bindings/js/DOMObjectHashTableMap.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2007 Samuel Weinig <sam@webkit.org> + * Copyright (C) 2009 Google, Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef DOMObjectHashTableMap_h +#define DOMObjectHashTableMap_h + +#include <runtime/Lookup.h> +#include <wtf/HashMap.h> + +namespace JSC { + class JSGlobalData; +} + +namespace WebCore { + +// 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; +}; + +} // namespace WebCore + +#endif // DOMObjectHashTableMap_h diff --git a/WebCore/bindings/js/DOMWrapperWorld.cpp b/WebCore/bindings/js/DOMWrapperWorld.cpp new file mode 100644 index 0000000..10c3fdd --- /dev/null +++ b/WebCore/bindings/js/DOMWrapperWorld.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2007 Samuel Weinig <sam@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "DOMWrapperWorld.h" + +#include "JSDOMWindow.h" +#include "ScriptController.h" +#include "WebCoreJSClientData.h" + +using namespace JSC; + +namespace WebCore { + +DOMWrapperWorld::DOMWrapperWorld(JSC::JSGlobalData* globalData, bool isNormal) + : m_globalData(globalData) + , m_isNormal(isNormal) + , m_isRegistered(false) +{ + registerWorld(); +} + +DOMWrapperWorld::~DOMWrapperWorld() +{ + unregisterWorld(); +} + +void DOMWrapperWorld::registerWorld() +{ + JSGlobalData::ClientData* clientData = m_globalData->clientData; + ASSERT(clientData); + static_cast<WebCoreJSClientData*>(clientData)->rememberWorld(this); + m_isRegistered = true; +} + +void DOMWrapperWorld::unregisterWorld() +{ + if (!m_isRegistered) + return; + m_isRegistered = false; + + JSGlobalData::ClientData* clientData = m_globalData->clientData; + ASSERT(clientData); + static_cast<WebCoreJSClientData*>(clientData)->forgetWorld(this); + + // These items are created lazily. + while (!m_documentsWithWrapperCaches.isEmpty()) + (*m_documentsWithWrapperCaches.begin())->destroyWrapperCache(this); + + while (!m_scriptControllersWithWindowShells.isEmpty()) + (*m_scriptControllersWithWindowShells.begin())->destroyWindowShell(this); +} + +DOMWrapperWorld* normalWorld(JSC::JSGlobalData& globalData) +{ + JSGlobalData::ClientData* clientData = globalData.clientData; + ASSERT(clientData); + return static_cast<WebCoreJSClientData*>(clientData)->normalWorld(); +} + +DOMWrapperWorld* mainThreadNormalWorld() +{ + ASSERT(isMainThread()); + static DOMWrapperWorld* cachedNormalWorld = normalWorld(*JSDOMWindow::commonJSGlobalData()); + return cachedNormalWorld; +} + +} // namespace WebCore diff --git a/WebCore/bindings/js/DOMWrapperWorld.h b/WebCore/bindings/js/DOMWrapperWorld.h new file mode 100644 index 0000000..832c5e0 --- /dev/null +++ b/WebCore/bindings/js/DOMWrapperWorld.h @@ -0,0 +1,97 @@ +/* + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2007 Samuel Weinig <sam@webkit.org> + * Copyright (C) 2009 Google, Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef DOMWrapperWorld_h +#define DOMWrapperWorld_h + +#include "Document.h" +#include "JSDOMGlobalObject.h" +#include "JSDOMWrapper.h" +#include <runtime/WeakGCMap.h> + +namespace WebCore { + +class ScriptController; +class StringImpl; + +typedef JSC::WeakGCMap<void*, DOMObject*> DOMObjectWrapperMap; +typedef JSC::WeakGCMap<StringImpl*, JSC::JSString*> JSStringCache; + +class DOMWrapperWorld : public RefCounted<DOMWrapperWorld> { +public: + static PassRefPtr<DOMWrapperWorld> create(JSC::JSGlobalData* globalData, bool isNormal = false) + { + return adoptRef(new DOMWrapperWorld(globalData, isNormal)); + } + ~DOMWrapperWorld(); + + void registerWorld(); + void unregisterWorld(); + + void didCreateWrapperCache(Document* document) { m_documentsWithWrapperCaches.add(document); } + void didDestroyWrapperCache(Document* document) { m_documentsWithWrapperCaches.remove(document); } + + void didCreateWindowShell(ScriptController* scriptController) { m_scriptControllersWithWindowShells.add(scriptController); } + void didDestroyWindowShell(ScriptController* scriptController) { m_scriptControllersWithWindowShells.remove(scriptController); } + + // FIXME: can we make this private? + DOMObjectWrapperMap m_wrappers; + JSStringCache m_stringCache; + + bool isNormal() const { return m_isNormal; } + +protected: + DOMWrapperWorld(JSC::JSGlobalData*, bool isNormal); + +private: + JSC::JSGlobalData* m_globalData; + HashSet<Document*> m_documentsWithWrapperCaches; + HashSet<ScriptController*> m_scriptControllersWithWindowShells; + bool m_isNormal; + bool m_isRegistered; +}; + +DOMWrapperWorld* normalWorld(JSC::JSGlobalData&); +DOMWrapperWorld* mainThreadNormalWorld(); +inline DOMWrapperWorld* debuggerWorld() { return mainThreadNormalWorld(); } +inline DOMWrapperWorld* pluginWorld() { return mainThreadNormalWorld(); } + +inline DOMWrapperWorld* currentWorld(JSC::ExecState* exec) +{ + return static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->world(); +} + +// From Document.h + +inline Document::JSWrapperCache* Document::getWrapperCache(DOMWrapperWorld* world) +{ + if (world->isNormal()) { + if (Document::JSWrapperCache* wrapperCache = m_normalWorldWrapperCache) + return wrapperCache; + ASSERT(!m_wrapperCacheMap.contains(world)); + } else if (Document::JSWrapperCache* wrapperCache = m_wrapperCacheMap.get(world)) + return wrapperCache; + return createWrapperCache(world); +} + +} // namespace WebCore + +#endif // DOMWrapperWorld_h diff --git a/WebCore/bindings/js/GCController.cpp b/WebCore/bindings/js/GCController.cpp index 3e5645f..d5a1789 100644 --- a/WebCore/bindings/js/GCController.cpp +++ b/WebCore/bindings/js/GCController.cpp @@ -71,7 +71,9 @@ void GCController::gcTimerFired(Timer<GCController>*) void GCController::garbageCollectNow() { - collect(0); + JSLock lock(SilenceAssertionsOnly); + if (!JSDOMWindow::commonJSGlobalData()->heap.isBusy()) + collect(0); } void GCController::garbageCollectOnAlternateThreadForDebugging(bool waitUntilDone) diff --git a/WebCore/bindings/js/JSAbstractWorkerCustom.cpp b/WebCore/bindings/js/JSAbstractWorkerCustom.cpp index 61fcf98..1f843f9 100644 --- a/WebCore/bindings/js/JSAbstractWorkerCustom.cpp +++ b/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), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); + impl()->addEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, 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), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); + impl()->removeEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSAttrCustom.cpp b/WebCore/bindings/js/JSAttrCustom.cpp index 3c01535..4cd40ac 100644 --- a/WebCore/bindings/js/JSAttrCustom.cpp +++ b/WebCore/bindings/js/JSAttrCustom.cpp @@ -33,6 +33,7 @@ #include "Document.h" #include "HTMLFrameElementBase.h" #include "HTMLNames.h" +#include "JSDOMBinding.h" using namespace JSC; @@ -46,13 +47,8 @@ void JSAttr::setValue(ExecState* exec, JSValue value) String attrValue = valueToStringWithNullCheck(exec, value); Element* ownerElement = imp->ownerElement(); - if (ownerElement && (ownerElement->hasTagName(iframeTag) || ownerElement->hasTagName(frameTag))) { - if (equalIgnoringCase(imp->name(), "src") && protocolIsJavaScript(deprecatedParseURL(attrValue))) { - Document* contentDocument = static_cast<HTMLFrameElementBase*>(ownerElement)->contentDocument(); - if (contentDocument && !checkNodeSecurity(exec, contentDocument)) - return; - } - } + if (ownerElement && !allowSettingSrcToJavascriptURL(exec, ownerElement, imp->name(), attrValue)) + return; ExceptionCode ec = 0; imp->setValue(attrValue, ec); diff --git a/WebCore/bindings/js/JSAudioConstructor.cpp b/WebCore/bindings/js/JSAudioConstructor.cpp index 77bb120..cc791d1 100644 --- a/WebCore/bindings/js/JSAudioConstructor.cpp +++ b/WebCore/bindings/js/JSAudioConstructor.cpp @@ -64,7 +64,7 @@ static JSObject* constructAudio(ExecState* exec, JSObject* constructor, const Ar // rather than looking at args.size. String src; if (args.size() > 0) - src = args.at(0).toString(exec); + src = ustringToString(args.at(0).toString(exec)); return asObject(toJS(exec, jsConstructor->globalObject(), HTMLAudioElement::createForJSConstructor(document, src))); } diff --git a/WebCore/bindings/js/JSBindingsAllInOne.cpp b/WebCore/bindings/js/JSBindingsAllInOne.cpp index 5a0820b..2e05350 100644 --- a/WebCore/bindings/js/JSBindingsAllInOne.cpp +++ b/WebCore/bindings/js/JSBindingsAllInOne.cpp @@ -113,6 +113,7 @@ #include "JSSVGMatrixCustom.cpp" #include "JSSVGPathSegCustom.cpp" #include "JSSVGPathSegListCustom.cpp" +#include "JSScriptProfileNodeCustom.cpp" #include "JSSharedWorkerConstructor.cpp" #include "JSSharedWorkerCustom.cpp" #include "JSStorageCustom.cpp" @@ -127,12 +128,14 @@ #include "JSWorkerConstructor.cpp" #include "JSWorkerContextBase.cpp" #include "JSWorkerContextCustom.cpp" +#include "JSWorkerContextErrorHandler.cpp" #include "JSWorkerCustom.cpp" #include "JSXMLHttpRequestConstructor.cpp" #include "JSXMLHttpRequestCustom.cpp" #include "JSXMLHttpRequestUploadCustom.cpp" #include "JSXSLTProcessorConstructor.cpp" #include "JSXSLTProcessorCustom.cpp" +#include "JavaScriptCallFrame.cpp" #include "ScheduledAction.cpp" #include "ScriptArray.cpp" #include "ScriptCachedFrameData.cpp" diff --git a/WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp b/WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp index 4a137d3..22bfee4 100644 --- a/WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp +++ b/WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp @@ -142,9 +142,9 @@ bool JSCSSStyleDeclaration::canGetItemsForName(ExecState*, CSSStyleDeclaration*, // FIXME: You can get these properties, and set them (see putDelegate below), // but you should also be able to enumerate them. -JSValue JSCSSStyleDeclaration::nameGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) +JSValue JSCSSStyleDeclaration::nameGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName) { - JSCSSStyleDeclaration* thisObj = static_cast<JSCSSStyleDeclaration*>(asObject(slot.slotBase())); + JSCSSStyleDeclaration* thisObj = static_cast<JSCSSStyleDeclaration*>(asObject(slotBase)); // Set up pixelOrPos boolean to handle the fact that // pixelTop returns "CSS Top" as number value in unit pixels @@ -165,7 +165,7 @@ JSValue JSCSSStyleDeclaration::nameGetter(ExecState* exec, const Identifier& pro // Make the SVG 'filter' attribute undetectable, to avoid confusion with the IE 'filter' attribute. if (propertyName == "filter") - return StringObjectThatMasqueradesAsUndefined::create(exec, thisObj->impl()->getPropertyValue(prop)); + return StringObjectThatMasqueradesAsUndefined::create(exec, stringToUString(thisObj->impl()->getPropertyValue(prop))); return jsString(exec, thisObj->impl()->getPropertyValue(prop)); } diff --git a/WebCore/bindings/js/JSCanvasRenderingContext2DCustom.cpp b/WebCore/bindings/js/JSCanvasRenderingContext2DCustom.cpp index a271923..7a776db 100644 --- a/WebCore/bindings/js/JSCanvasRenderingContext2DCustom.cpp +++ b/WebCore/bindings/js/JSCanvasRenderingContext2DCustom.cpp @@ -54,7 +54,7 @@ static JSValue toJS(ExecState* exec, CanvasStyle* style) static PassRefPtr<CanvasStyle> toHTMLCanvasStyle(ExecState* exec, JSValue value) { if (value.isString()) - return CanvasStyle::create(asString(value)->value(exec)); + return CanvasStyle::create(ustringToString(asString(value)->value(exec))); if (!value.isObject()) return 0; JSObject* object = asObject(value); @@ -102,13 +102,13 @@ JSValue JSCanvasRenderingContext2D::setFillColor(ExecState* exec, const ArgList& switch (args.size()) { case 1: if (args.at(0).isString()) - context->setFillColor(asString(args.at(0))->value(exec)); + context->setFillColor(ustringToString(asString(args.at(0))->value(exec))); else context->setFillColor(args.at(0).toFloat(exec)); break; case 2: if (args.at(0).isString()) - context->setFillColor(asString(args.at(0))->value(exec), args.at(1).toFloat(exec)); + context->setFillColor(ustringToString(asString(args.at(0))->value(exec)), args.at(1).toFloat(exec)); else context->setFillColor(args.at(0).toFloat(exec), args.at(1).toFloat(exec)); break; @@ -139,13 +139,13 @@ JSValue JSCanvasRenderingContext2D::setStrokeColor(ExecState* exec, const ArgLis switch (args.size()) { case 1: if (args.at(0).isString()) - context->setStrokeColor(asString(args.at(0))->value(exec)); + context->setStrokeColor(ustringToString(asString(args.at(0))->value(exec))); else context->setStrokeColor(args.at(0).toFloat(exec)); break; case 2: if (args.at(0).isString()) - context->setStrokeColor(asString(args.at(0))->value(exec), args.at(1).toFloat(exec)); + context->setStrokeColor(ustringToString(asString(args.at(0))->value(exec)), args.at(1).toFloat(exec)); else context->setStrokeColor(args.at(0).toFloat(exec), args.at(1).toFloat(exec)); break; @@ -198,7 +198,7 @@ JSValue JSCanvasRenderingContext2D::drawImage(ExecState* exec, const ArgList& ar HTMLImageElement* imgElt = static_cast<HTMLImageElement*>(static_cast<JSHTMLElement*>(o)->impl()); switch (args.size()) { case 3: - context->drawImage(imgElt, args.at(1).toFloat(exec), args.at(2).toFloat(exec)); + context->drawImage(imgElt, args.at(1).toFloat(exec), args.at(2).toFloat(exec), ec); break; case 5: context->drawImage(imgElt, args.at(1).toFloat(exec), args.at(2).toFloat(exec), @@ -219,7 +219,7 @@ JSValue JSCanvasRenderingContext2D::drawImage(ExecState* exec, const ArgList& ar HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(static_cast<JSHTMLElement*>(o)->impl()); switch (args.size()) { case 3: - context->drawImage(canvas, args.at(1).toFloat(exec), args.at(2).toFloat(exec)); + context->drawImage(canvas, args.at(1).toFloat(exec), args.at(2).toFloat(exec), ec); break; case 5: context->drawImage(canvas, args.at(1).toFloat(exec), args.at(2).toFloat(exec), @@ -241,7 +241,7 @@ JSValue JSCanvasRenderingContext2D::drawImage(ExecState* exec, const ArgList& ar HTMLVideoElement* video = static_cast<HTMLVideoElement*>(static_cast<JSHTMLElement*>(o)->impl()); switch (args.size()) { case 3: - context->drawImage(video, args.at(1).toFloat(exec), args.at(2).toFloat(exec)); + context->drawImage(video, args.at(1).toFloat(exec), args.at(2).toFloat(exec), ec); break; case 5: context->drawImage(video, args.at(1).toFloat(exec), args.at(2).toFloat(exec), @@ -282,7 +282,7 @@ JSValue JSCanvasRenderingContext2D::drawImageFromRect(ExecState* exec, const Arg args.at(3).toFloat(exec), args.at(4).toFloat(exec), args.at(5).toFloat(exec), args.at(6).toFloat(exec), args.at(7).toFloat(exec), args.at(8).toFloat(exec), - args.at(9).toString(exec)); + ustringToString(args.at(9).toString(exec))); return jsUndefined(); } @@ -298,7 +298,7 @@ JSValue JSCanvasRenderingContext2D::setShadow(ExecState* exec, const ArgList& ar case 4: if (args.at(3).isString()) context->setShadow(args.at(0).toFloat(exec), args.at(1).toFloat(exec), - args.at(2).toFloat(exec), asString(args.at(3))->value(exec)); + args.at(2).toFloat(exec), ustringToString(asString(args.at(3))->value(exec))); else context->setShadow(args.at(0).toFloat(exec), args.at(1).toFloat(exec), args.at(2).toFloat(exec), args.at(3).toFloat(exec)); @@ -306,7 +306,7 @@ JSValue JSCanvasRenderingContext2D::setShadow(ExecState* exec, const ArgList& ar case 5: if (args.at(3).isString()) context->setShadow(args.at(0).toFloat(exec), args.at(1).toFloat(exec), - args.at(2).toFloat(exec), asString(args.at(3))->value(exec), + args.at(2).toFloat(exec), ustringToString(asString(args.at(3))->value(exec)), args.at(4).toFloat(exec)); else context->setShadow(args.at(0).toFloat(exec), args.at(1).toFloat(exec), @@ -391,9 +391,9 @@ JSValue JSCanvasRenderingContext2D::fillText(ExecState* exec, const ArgList& arg return throwError(exec, SyntaxError); if (args.size() == 4) - context->fillText(args.at(0).toString(exec), args.at(1).toFloat(exec), args.at(2).toFloat(exec), args.at(3).toFloat(exec)); + context->fillText(ustringToString(args.at(0).toString(exec)), args.at(1).toFloat(exec), args.at(2).toFloat(exec), args.at(3).toFloat(exec)); else - context->fillText(args.at(0).toString(exec), args.at(1).toFloat(exec), args.at(2).toFloat(exec)); + context->fillText(ustringToString(args.at(0).toString(exec)), args.at(1).toFloat(exec), args.at(2).toFloat(exec)); return jsUndefined(); } @@ -409,9 +409,9 @@ JSValue JSCanvasRenderingContext2D::strokeText(ExecState* exec, const ArgList& a return throwError(exec, SyntaxError); if (args.size() == 4) - context->strokeText(args.at(0).toString(exec), args.at(1).toFloat(exec), args.at(2).toFloat(exec), args.at(3).toFloat(exec)); + context->strokeText(ustringToString(args.at(0).toString(exec)), args.at(1).toFloat(exec), args.at(2).toFloat(exec), args.at(3).toFloat(exec)); else - context->strokeText(args.at(0).toString(exec), args.at(1).toFloat(exec), args.at(2).toFloat(exec)); + context->strokeText(ustringToString(args.at(0).toString(exec)), args.at(1).toFloat(exec), args.at(2).toFloat(exec)); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSClipboardCustom.cpp b/WebCore/bindings/js/JSClipboardCustom.cpp index 78dca49..7efd2b0 100644 --- a/WebCore/bindings/js/JSClipboardCustom.cpp +++ b/WebCore/bindings/js/JSClipboardCustom.cpp @@ -59,7 +59,7 @@ JSValue JSClipboard::types(ExecState* exec) const MarkedArgumentBuffer list; HashSet<String>::const_iterator end = types.end(); for (HashSet<String>::const_iterator it = types.begin(); it != end; ++it) - list.append(jsString(exec, UString(*it))); + list.append(jsString(exec, stringToUString(*it))); return constructArray(exec, list); } @@ -73,7 +73,7 @@ JSValue JSClipboard::clearData(ExecState* exec, const ArgList& args) } if (args.size() == 1) { - clipboard->clearData(args.at(0).toString(exec)); + clipboard->clearData(ustringToString(args.at(0).toString(exec))); return jsUndefined(); } @@ -90,7 +90,7 @@ JSValue JSClipboard::getData(ExecState* exec, const ArgList& args) Clipboard* clipboard = impl(); bool success; - String result = clipboard->getData(args.at(0).toString(exec), success); + String result = clipboard->getData(ustringToString(args.at(0).toString(exec)), success); if (!success) return jsUndefined(); @@ -105,7 +105,7 @@ JSValue JSClipboard::setData(ExecState* exec, const ArgList& args) if (args.size() != 2) return throwError(exec, SyntaxError, "setData: Invalid number of arguments"); - return jsBoolean(clipboard->setData(args.at(0).toString(exec), args.at(1).toString(exec))); + return jsBoolean(clipboard->setData(ustringToString(args.at(0).toString(exec)), ustringToString(args.at(1).toString(exec)))); } JSValue JSClipboard::setDragImage(ExecState* exec, const ArgList& args) diff --git a/WebCore/bindings/js/JSConsoleCustom.cpp b/WebCore/bindings/js/JSConsoleCustom.cpp index b631cdd..3ad34a3 100644 --- a/WebCore/bindings/js/JSConsoleCustom.cpp +++ b/WebCore/bindings/js/JSConsoleCustom.cpp @@ -28,8 +28,9 @@ #include "JSConsole.h" #include "Console.h" -#include "JavaScriptProfile.h" +#include "JSScriptProfile.h" #include "ScriptCallStack.h" +#include "ScriptProfile.h" #include <runtime/JSArray.h> using namespace JSC; @@ -38,7 +39,7 @@ namespace WebCore { #if ENABLE(JAVASCRIPT_DEBUGGER) -typedef Vector<RefPtr<JSC::Profile> > ProfilesArray; +typedef Vector<RefPtr<ScriptProfile> > ProfilesArray; JSValue JSConsole::profiles(ExecState* exec) const { diff --git a/WebCore/bindings/js/JSCustomPositionCallback.cpp b/WebCore/bindings/js/JSCustomPositionCallback.cpp index e5f83aa..cc6d45c 100644 --- a/WebCore/bindings/js/JSCustomPositionCallback.cpp +++ b/WebCore/bindings/js/JSCustomPositionCallback.cpp @@ -26,6 +26,8 @@ #include "config.h" #include "JSCustomPositionCallback.h" +#if ENABLE(GEOLOCATION) + #include "Frame.h" #include "JSGeoposition.h" #include "ScriptController.h" @@ -52,3 +54,5 @@ void JSCustomPositionCallback::handleEvent(Geoposition* geoposition) } } // namespace WebCore + +#endif // ENABLE(GEOLOCATION) diff --git a/WebCore/bindings/js/JSCustomPositionErrorCallback.cpp b/WebCore/bindings/js/JSCustomPositionErrorCallback.cpp index bd64deb..c94ae9a 100644 --- a/WebCore/bindings/js/JSCustomPositionErrorCallback.cpp +++ b/WebCore/bindings/js/JSCustomPositionErrorCallback.cpp @@ -26,6 +26,8 @@ #include "config.h" #include "JSCustomPositionErrorCallback.h" +#if ENABLE(GEOLOCATION) + #include "Frame.h" #include "JSPositionError.h" #include "ScriptController.h" @@ -53,3 +55,5 @@ void JSCustomPositionErrorCallback::handleEvent(PositionError* positionError) } } // namespace WebCore + +#endif // ENABLE(GEOLOCATION) diff --git a/WebCore/bindings/js/JSCustomSQLStatementCallback.cpp b/WebCore/bindings/js/JSCustomSQLStatementCallback.cpp index 1f6bd95..46a7ae5 100644 --- a/WebCore/bindings/js/JSCustomSQLStatementCallback.cpp +++ b/WebCore/bindings/js/JSCustomSQLStatementCallback.cpp @@ -32,21 +32,22 @@ #if ENABLE(DATABASE) #include "Frame.h" -#include "ScriptController.h" #include "JSSQLResultSet.h" #include "JSSQLTransaction.h" +#include "ScriptExecutionContext.h" #include <runtime/JSLock.h> #include <wtf/MainThread.h> namespace WebCore { - + using namespace JSC; - + JSCustomSQLStatementCallback::JSCustomSQLStatementCallback(JSObject* callback, JSDOMGlobalObject* globalObject) : m_data(new JSCallbackData(callback, globalObject)) + , m_isolatedWorld(globalObject->world()) { } - + JSCustomSQLStatementCallback::~JSCustomSQLStatementCallback() { callOnMainThread(JSCallbackData::deleteData, m_data); @@ -55,14 +56,19 @@ JSCustomSQLStatementCallback::~JSCustomSQLStatementCallback() #endif } -void JSCustomSQLStatementCallback::handleEvent(SQLTransaction* transaction, SQLResultSet* resultSet, bool& raisedException) +void JSCustomSQLStatementCallback::handleEvent(ScriptExecutionContext* context, SQLTransaction* transaction, SQLResultSet* resultSet, bool& raisedException) { ASSERT(m_data); + ASSERT(context); RefPtr<JSCustomSQLStatementCallback> protect(this); JSC::JSLock lock(SilenceAssertionsOnly); - ExecState* exec = m_data->globalObject()->globalExec(); + JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(context, m_isolatedWorld.get()); + if (!globalObject) + return; + + ExecState* exec = globalObject->globalExec(); MarkedArgumentBuffer args; args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), transaction)); args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), resultSet)); diff --git a/WebCore/bindings/js/JSCustomSQLStatementCallback.h b/WebCore/bindings/js/JSCustomSQLStatementCallback.h index 259aecf..cb7b34d 100644 --- a/WebCore/bindings/js/JSCustomSQLStatementCallback.h +++ b/WebCore/bindings/js/JSCustomSQLStatementCallback.h @@ -45,15 +45,16 @@ public: { return adoptRef(new JSCustomSQLStatementCallback(callback, globalObject)); } - + virtual ~JSCustomSQLStatementCallback(); - virtual void handleEvent(SQLTransaction*, SQLResultSet*, bool& raisedException); + virtual void handleEvent(ScriptExecutionContext*, SQLTransaction*, SQLResultSet*, bool& raisedException); private: JSCustomSQLStatementCallback(JSC::JSObject* callback, JSDOMGlobalObject*); JSCallbackData* m_data; + RefPtr<DOMWrapperWorld> m_isolatedWorld; }; } diff --git a/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.cpp b/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.cpp index 4d5de79..a2ba52a 100644 --- a/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.cpp +++ b/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.cpp @@ -35,16 +35,17 @@ #include "JSCallbackData.h" #include "JSSQLError.h" #include "JSSQLTransaction.h" -#include "ScriptController.h" +#include "ScriptExecutionContext.h" #include <runtime/JSLock.h> #include <wtf/MainThread.h> namespace WebCore { - + using namespace JSC; - + JSCustomSQLStatementErrorCallback::JSCustomSQLStatementErrorCallback(JSObject* callback, JSDOMGlobalObject* globalObject) : m_data(new JSCallbackData(callback, globalObject)) + , m_isolatedWorld(globalObject->world()) { } @@ -56,18 +57,23 @@ JSCustomSQLStatementErrorCallback::~JSCustomSQLStatementErrorCallback() #endif } -bool JSCustomSQLStatementErrorCallback::handleEvent(SQLTransaction* transaction, SQLError* error) +bool JSCustomSQLStatementErrorCallback::handleEvent(ScriptExecutionContext* context, SQLTransaction* transaction, SQLError* error) { ASSERT(m_data); - + ASSERT(context); + RefPtr<JSCustomSQLStatementErrorCallback> protect(this); - + JSC::JSLock lock(SilenceAssertionsOnly); - ExecState* exec = m_data->globalObject()->globalExec(); + JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(context, m_isolatedWorld.get()); + if (!globalObject) + return true; // if we cannot invoke the callback, roll back the transaction + + ExecState* exec = globalObject->globalExec(); MarkedArgumentBuffer args; args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), transaction)); args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), error)); - + bool raisedException = false; JSValue result = m_data->invokeCallback(args, &raisedException); if (raisedException) { @@ -77,7 +83,7 @@ bool JSCustomSQLStatementErrorCallback::handleEvent(SQLTransaction* transaction, // Therefore an exception and returning true are the same thing - so, return true on an exception return true; } - return !result.isFalse(); + return result.toBoolean(exec); } } diff --git a/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.h b/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.h index ac4e45f..b1b0792 100644 --- a/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.h +++ b/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.h @@ -31,16 +31,15 @@ #if ENABLE(DATABASE) -#include "JSDOMGlobalObject.h" +#include "JSCallbackData.h" #include "SQLStatementErrorCallback.h" -#include <runtime/Protect.h> #include <wtf/Forward.h> namespace WebCore { -class JSCallbackData; +class JSCallbackData; class SQLError; - + class JSCustomSQLStatementErrorCallback : public SQLStatementErrorCallback { public: static PassRefPtr<JSCustomSQLStatementErrorCallback> create(JSC::JSObject* callback, JSDOMGlobalObject* globalObject) @@ -50,17 +49,17 @@ public: virtual ~JSCustomSQLStatementErrorCallback(); - virtual bool handleEvent(SQLTransaction*, SQLError*); + virtual bool handleEvent(ScriptExecutionContext*, SQLTransaction*, SQLError*); private: JSCustomSQLStatementErrorCallback(JSC::JSObject* callback, JSDOMGlobalObject*); JSCallbackData* m_data; + RefPtr<DOMWrapperWorld> m_isolatedWorld; }; - + } #endif // ENABLE(DATABASE) #endif // JSCustomSQLStatementErrorCallback_h - diff --git a/WebCore/bindings/js/JSCustomSQLTransactionCallback.cpp b/WebCore/bindings/js/JSCustomSQLTransactionCallback.cpp index 456022f..d5e9754 100644 --- a/WebCore/bindings/js/JSCustomSQLTransactionCallback.cpp +++ b/WebCore/bindings/js/JSCustomSQLTransactionCallback.cpp @@ -33,24 +33,23 @@ #include "Frame.h" #include "JSCallbackData.h" -#include "JSDOMGlobalObject.h" #include "JSSQLTransaction.h" -#include "Page.h" -#include "ScriptController.h" +#include "ScriptExecutionContext.h" #include <runtime/JSLock.h> #include <wtf/MainThread.h> #include <wtf/RefCountedLeakCounter.h> namespace WebCore { - + using namespace JSC; - + #ifndef NDEBUG static WTF::RefCountedLeakCounter counter("JSCustomSQLTransactionCallback"); #endif JSCustomSQLTransactionCallback::JSCustomSQLTransactionCallback(JSObject* callback, JSDOMGlobalObject* globalObject) : m_data(new JSCallbackData(callback, globalObject)) + , m_isolatedWorld(globalObject->world()) { #ifndef NDEBUG counter.increment(); @@ -66,19 +65,24 @@ JSCustomSQLTransactionCallback::~JSCustomSQLTransactionCallback() #endif } -void JSCustomSQLTransactionCallback::handleEvent(SQLTransaction* transaction, bool& raisedException) +void JSCustomSQLTransactionCallback::handleEvent(ScriptExecutionContext* context, SQLTransaction* transaction, bool& raisedException) { ASSERT(m_data); + ASSERT(context); RefPtr<JSCustomSQLTransactionCallback> protect(this); - + JSC::JSLock lock(SilenceAssertionsOnly); - ExecState* exec = m_data->globalObject()->globalExec(); + JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(context, m_isolatedWorld.get()); + if (!globalObject) + return; + + ExecState* exec = globalObject->globalExec(); MarkedArgumentBuffer args; args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), transaction)); m_data->invokeCallback(args, &raisedException); } - + } #endif // ENABLE(DATABASE) diff --git a/WebCore/bindings/js/JSCustomSQLTransactionCallback.h b/WebCore/bindings/js/JSCustomSQLTransactionCallback.h index f142e59..bf2ae68 100644 --- a/WebCore/bindings/js/JSCustomSQLTransactionCallback.h +++ b/WebCore/bindings/js/JSCustomSQLTransactionCallback.h @@ -31,12 +31,9 @@ #if ENABLE(DATABASE) +#include "JSDOMGlobalObject.h" #include "SQLTransactionCallback.h" -#include <wtf/PassRefPtr.h> - -namespace JSC { - class JSObject; -} +#include <wtf/Forward.h> namespace WebCore { @@ -52,13 +49,14 @@ public: } virtual ~JSCustomSQLTransactionCallback(); - - virtual void handleEvent(SQLTransaction*, bool& raisedException); + + virtual void handleEvent(ScriptExecutionContext*, SQLTransaction*, bool& raisedException); private: JSCustomSQLTransactionCallback(JSC::JSObject* callback, JSDOMGlobalObject*); JSCallbackData* m_data; + RefPtr<DOMWrapperWorld> m_isolatedWorld; }; } diff --git a/WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.cpp b/WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.cpp index 331e014..09ff340 100644 --- a/WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.cpp +++ b/WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.cpp @@ -34,16 +34,17 @@ #include "Frame.h" #include "JSCallbackData.h" #include "JSSQLError.h" -#include "ScriptController.h" +#include "ScriptExecutionContext.h" #include <runtime/JSLock.h> #include <wtf/MainThread.h> namespace WebCore { - + using namespace JSC; - + JSCustomSQLTransactionErrorCallback::JSCustomSQLTransactionErrorCallback(JSObject* callback, JSDOMGlobalObject* globalObject) : m_data(new JSCallbackData(callback, globalObject)) + , m_isolatedWorld(globalObject->world()) { } @@ -55,14 +56,19 @@ JSCustomSQLTransactionErrorCallback::~JSCustomSQLTransactionErrorCallback() #endif } -void JSCustomSQLTransactionErrorCallback::handleEvent(SQLError* error) +void JSCustomSQLTransactionErrorCallback::handleEvent(ScriptExecutionContext* context, SQLError* error) { ASSERT(m_data); + ASSERT(context); RefPtr<JSCustomSQLTransactionErrorCallback> protect(this); JSC::JSLock lock(SilenceAssertionsOnly); - ExecState* exec = m_data->globalObject()->globalExec(); + JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(context, m_isolatedWorld.get()); + if (!globalObject) + return; + + ExecState* exec = globalObject->globalExec(); MarkedArgumentBuffer args; args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), error)); m_data->invokeCallback(args); diff --git a/WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.h b/WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.h index 54bf33b..bb92393 100644 --- a/WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.h +++ b/WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.h @@ -31,9 +31,8 @@ #if ENABLE(DATABASE) +#include "JSCallbackData.h" #include "SQLTransactionErrorCallback.h" -#include "JSDOMGlobalObject.h" -#include <runtime/Protect.h> #include <wtf/Forward.h> namespace WebCore { @@ -47,15 +46,16 @@ public: { return adoptRef(new JSCustomSQLTransactionErrorCallback(callback, globalObject)); } - + virtual ~JSCustomSQLTransactionErrorCallback(); - - virtual void handleEvent(SQLError*); + + virtual void handleEvent(ScriptExecutionContext*, SQLError*); private: JSCustomSQLTransactionErrorCallback(JSC::JSObject* callback, JSDOMGlobalObject* globalObject); JSCallbackData* m_data; + RefPtr<DOMWrapperWorld> m_isolatedWorld; }; } diff --git a/WebCore/bindings/js/JSCustomXPathNSResolver.cpp b/WebCore/bindings/js/JSCustomXPathNSResolver.cpp index 07cfc74..e7d174f 100644 --- a/WebCore/bindings/js/JSCustomXPathNSResolver.cpp +++ b/WebCore/bindings/js/JSCustomXPathNSResolver.cpp @@ -98,7 +98,7 @@ String JSCustomXPathNSResolver::lookupNamespaceURI(const String& prefix) reportCurrentException(exec); else { if (!retval.isUndefinedOrNull()) - result = retval.toString(exec); + result = ustringToString(retval.toString(exec)); } Document::updateStyleForAllDocuments(); diff --git a/WebCore/bindings/js/JSDOMApplicationCacheCustom.cpp b/WebCore/bindings/js/JSDOMApplicationCacheCustom.cpp index 5637087..6198d6e 100644 --- a/WebCore/bindings/js/JSDOMApplicationCacheCustom.cpp +++ b/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), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); + impl()->addEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, 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), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); + impl()->removeEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSDOMBinding.cpp b/WebCore/bindings/js/JSDOMBinding.cpp index abba405..a4c3d6a 100644 --- a/WebCore/bindings/js/JSDOMBinding.cpp +++ b/WebCore/bindings/js/JSDOMBinding.cpp @@ -24,7 +24,9 @@ #include "debugger/DebuggerCallFrame.h" #include "ActiveDOMObject.h" +#include "CSSHelper.h" #include "DOMCoreException.h" +#include "DOMObjectHashTableMap.h" #include "Document.h" #include "EventException.h" #include "ExceptionBase.h" @@ -32,11 +34,13 @@ #include "Frame.h" #include "HTMLAudioElement.h" #include "HTMLCanvasElement.h" +#include "HTMLFrameElementBase.h" #include "HTMLImageElement.h" -#include "HTMLScriptElement.h" #include "HTMLNames.h" +#include "HTMLScriptElement.h" #include "JSDOMCoreException.h" #include "JSDOMWindowCustom.h" +#include "JSDebugWrapperSet.h" #include "JSEventException.h" #include "JSExceptionBase.h" #include "JSNode.h" @@ -48,6 +52,7 @@ #include "ScriptCachedFrameData.h" #include "ScriptController.h" #include "Settings.h" +#include "WebCoreJSClientData.h" #include "XMLHttpRequestException.h" #include <runtime/DateInstance.h> #include <runtime/Error.h> @@ -66,11 +71,6 @@ #include "XPathException.h" #endif -#if ENABLE(WORKERS) -#include <wtf/ThreadSpecific.h> -using namespace WTF; -#endif - using namespace JSC; namespace WebCore { @@ -80,85 +80,6 @@ using namespace HTMLNames; typedef Document::JSWrapperCache JSWrapperCache; typedef Document::JSWrapperCacheMap JSWrapperCacheMap; -inline JSWrapperCache* Document::getWrapperCache(DOMWrapperWorld* world) -{ - if (world->isNormal()) { - if (JSWrapperCache* wrapperCache = m_normalWorldWrapperCache) - return wrapperCache; - ASSERT(!m_wrapperCacheMap.contains(world)); - } else if (JSWrapperCache* wrapperCache = m_wrapperCacheMap.get(world)) - return wrapperCache; - return createWrapperCache(world); -} - -// For debugging, keep a set of wrappers currently cached, and check that -// all are uncached before they are destroyed. This helps us catch bugs like: -// - wrappers being deleted without being removed from the cache -// - wrappers being cached twice - -static void willCacheWrapper(DOMObject* wrapper); -static void didUncacheWrapper(DOMObject* wrapper); - -#ifdef NDEBUG - -static inline void willCacheWrapper(DOMObject*) -{ -} - -static inline void didUncacheWrapper(DOMObject*) -{ -} - -#else - -static HashSet<DOMObject*>& wrapperSet() -{ -#if ENABLE(WORKERS) - DEFINE_STATIC_LOCAL(ThreadSpecific<HashSet<DOMObject*> >, staticWrapperSet, ()); - return *staticWrapperSet; -#else - DEFINE_STATIC_LOCAL(HashSet<DOMObject*>, staticWrapperSet, ()); - return staticWrapperSet; -#endif -} - -static void willCacheWrapper(DOMObject* wrapper) -{ - ASSERT(!wrapperSet().contains(wrapper)); - wrapperSet().add(wrapper); -} - -static void didUncacheWrapper(DOMObject* wrapper) -{ - if (!wrapper) - return; - ASSERT(wrapperSet().contains(wrapper)); - wrapperSet().remove(wrapper); -} - -DOMObject::~DOMObject() -{ - ASSERT(!wrapperSet().contains(this)); -} - -#endif - -DOMWrapperWorld::DOMWrapperWorld(JSC::JSGlobalData* globalData, bool isNormal) - : m_globalData(globalData) - , m_isNormal(isNormal) -{ -} - -DOMWrapperWorld::~DOMWrapperWorld() -{ - JSGlobalData::ClientData* clientData = m_globalData->clientData; - ASSERT(clientData); - static_cast<WebCoreJSClientData*>(clientData)->forgetWorld(this); - - for (HashSet<Document*>::iterator iter = documentsWithWrappers.begin(); iter != documentsWithWrappers.end(); ++iter) - forgetWorldOfDOMNodesForDocument(*iter, this); -} - class JSGlobalDataWorldIterator { public: JSGlobalDataWorldIterator(JSGlobalData* globalData) @@ -195,37 +116,11 @@ private: HashSet<DOMWrapperWorld*>::iterator m_end; }; -DOMWrapperWorld* normalWorld(JSC::JSGlobalData& globalData) -{ - JSGlobalData::ClientData* clientData = globalData.clientData; - ASSERT(clientData); - return static_cast<WebCoreJSClientData*>(clientData)->normalWorld(); -} - -DOMWrapperWorld* mainThreadNormalWorld() -{ - ASSERT(isMainThread()); - static DOMWrapperWorld* cachedNormalWorld = normalWorld(*JSDOMWindow::commonJSGlobalData()); - return cachedNormalWorld; -} - -DOMObjectHashTableMap& DOMObjectHashTableMap::mapFor(JSGlobalData& globalData) -{ - JSGlobalData::ClientData* clientData = globalData.clientData; - ASSERT(clientData); - return static_cast<WebCoreJSClientData*>(clientData)->hashTableMap; -} - const JSC::HashTable* getHashTableForGlobalData(JSGlobalData& globalData, const JSC::HashTable* staticTable) { return DOMObjectHashTableMap::mapFor(globalData).get(staticTable); } -static inline DOMObjectWrapperMap& DOMObjectWrapperMapFor(JSC::ExecState* exec) -{ - return currentWorld(exec)->m_wrappers; -} - bool hasCachedDOMObjectWrapperUnchecked(JSGlobalData* globalData, void* objectHandle) { for (JSGlobalDataWorldIterator worldIter(globalData); worldIter; ++worldIter) { @@ -246,13 +141,13 @@ bool hasCachedDOMObjectWrapper(JSGlobalData* globalData, void* objectHandle) DOMObject* getCachedDOMObjectWrapper(JSC::ExecState* exec, void* objectHandle) { - return DOMObjectWrapperMapFor(exec).get(objectHandle); + return domObjectWrapperMapFor(exec).get(objectHandle); } void cacheDOMObjectWrapper(JSC::ExecState* exec, void* objectHandle, DOMObject* wrapper) { - willCacheWrapper(wrapper); - DOMObjectWrapperMapFor(exec).set(objectHandle, wrapper); + JSDebugWrapperSet::willCacheWrapper(wrapper); + domObjectWrapperMapFor(exec).set(objectHandle, wrapper); } bool hasCachedDOMNodeWrapperUnchecked(Document* document, Node* node) @@ -268,13 +163,6 @@ bool hasCachedDOMNodeWrapperUnchecked(Document* document, Node* node) return false; } -JSNode* getCachedDOMNodeWrapper(JSC::ExecState* exec, Document* document, Node* node) -{ - if (document) - return document->getWrapperCache(currentWorld(exec))->get(node); - return static_cast<JSNode*>(DOMObjectWrapperMapFor(exec).get(node)); -} - void forgetDOMObject(DOMObject* wrapper, void* objectHandle) { JSC::JSGlobalData* globalData = Heap::heap(wrapper)->globalData(); @@ -284,7 +172,7 @@ void forgetDOMObject(DOMObject* wrapper, void* objectHandle) ASSERT(clientData); DOMObjectWrapperMap& wrappers = static_cast<WebCoreJSClientData*>(clientData)->normalWorld()->m_wrappers; if (wrappers.uncheckedRemove(objectHandle, wrapper)) { - didUncacheWrapper(wrapper); + JSDebugWrapperSet::didUncacheWrapper(wrapper); return; } @@ -294,11 +182,13 @@ void forgetDOMObject(DOMObject* wrapper, void* objectHandle) if (worldIter->m_wrappers.uncheckedRemove(objectHandle, wrapper)) break; } - didUncacheWrapper(wrapper); + JSDebugWrapperSet::didUncacheWrapper(wrapper); } void forgetDOMNode(JSNode* wrapper, Node* node, Document* document) { + node->clearWrapper(wrapper); + if (!document) { forgetDOMObject(wrapper, node); return; @@ -311,36 +201,20 @@ void forgetDOMNode(JSNode* wrapper, Node* node, Document* document) if (wrappersIter->second->uncheckedRemove(node, wrapper)) break; } - didUncacheWrapper(wrapper); + JSDebugWrapperSet::didUncacheWrapper(wrapper); } void cacheDOMNodeWrapper(JSC::ExecState* exec, Document* document, Node* node, JSNode* wrapper) { - if (!document) { - willCacheWrapper(wrapper); - DOMObjectWrapperMapFor(exec).set(node, wrapper); - return; - } - willCacheWrapper(wrapper); - document->getWrapperCache(currentWorld(exec))->set(node, wrapper); -} + JSDebugWrapperSet::willCacheWrapper(wrapper); -void forgetAllDOMNodesForDocument(Document* document) -{ - ASSERT(document); - JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap(); - JSWrapperCacheMap::const_iterator wrappersMapEnd = wrapperCacheMap.end(); - for (JSWrapperCacheMap::const_iterator wrappersMapIter = wrapperCacheMap.begin(); wrappersMapIter != wrappersMapEnd; ++wrappersMapIter) { - delete wrappersMapIter->second; - wrappersMapIter->first->forgetDocument(document); - } -} + if (!document) + domObjectWrapperMapFor(exec).set(node, wrapper); + else + document->getWrapperCache(currentWorld(exec))->set(node, wrapper); -void forgetWorldOfDOMNodesForDocument(Document* document, DOMWrapperWorld* world) -{ - JSWrapperCache* wrappers = document->wrapperCacheMap().take(world); - ASSERT(wrappers); // 'world' should only know about 'document' if 'document' knows about 'world'! - delete wrappers; + if (currentWorld(exec)->isNormal()) + node->setWrapper(wrapper); } static inline bool isObservableThroughDOM(JSNode* jsNode, DOMWrapperWorld* world) @@ -464,7 +338,7 @@ static inline void takeWrappers(Node* node, Document* document, WrapperSet& wrap JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap(); for (JSWrapperCacheMap::iterator iter = wrapperCacheMap.begin(); iter != wrapperCacheMap.end(); ++iter) { if (JSNode* wrapper = iter->second->take(node)) { - didUncacheWrapper(wrapper); + JSDebugWrapperSet::didUncacheWrapper(wrapper); wrapperSet.append(WrapperAndWorld(wrapper, iter->first)); } } @@ -472,7 +346,7 @@ static inline void takeWrappers(Node* node, Document* document, WrapperSet& wrap for (JSGlobalDataWorldIterator worldIter(JSDOMWindow::commonJSGlobalData()); worldIter; ++worldIter) { DOMWrapperWorld* world = *worldIter; if (JSNode* wrapper = static_cast<JSNode*>(world->m_wrappers.take(node))) { - didUncacheWrapper(wrapper); + JSDebugWrapperSet::didUncacheWrapper(wrapper); wrapperSet.append(WrapperAndWorld(wrapper, world)); } } @@ -488,7 +362,7 @@ void updateDOMNodeDocument(Node* node, Document* oldDocument, Document* newDocum for (unsigned i = 0; i < wrapperSet.size(); ++i) { JSNode* wrapper = wrapperSet[i].first; - willCacheWrapper(wrapper); + JSDebugWrapperSet::willCacheWrapper(wrapper); if (newDocument) newDocument->getWrapperCache(wrapperSet[i].second)->set(node, wrapper); else @@ -556,7 +430,7 @@ JSValue jsStringSlowCase(ExecState* exec, JSStringCache& stringCache, StringImpl if (JSString* wrapper = stringCache.uncheckedGet(stringImpl)) stringCache.uncheckedRemove(stringImpl, wrapper); - JSString* wrapper = jsStringWithFinalizer(exec, stringImpl->ustring(), stringWrapperDestroyed, stringImpl); + JSString* wrapper = jsStringWithFinalizer(exec, UString(stringImpl), stringWrapperDestroyed, stringImpl); stringCache.set(stringImpl, wrapper); // ref explicitly instead of using a RefPtr-keyed hashtable because the wrapper can // outlive the cache, so the stringImpl has to match the wrapper's lifetime. @@ -618,18 +492,27 @@ JSValue jsStringOrFalse(ExecState* exec, const KURL& url) return jsString(exec, url.string()); } -UString valueToStringWithNullCheck(ExecState* exec, JSValue value) +AtomicStringImpl* findAtomicString(const Identifier& identifier) +{ + if (identifier.isNull()) + return 0; + UStringImpl* impl = identifier.ustring().rep(); + ASSERT(impl->existingHash()); + return AtomicString::find(impl->characters(), impl->length(), impl->existingHash()); +} + +String valueToStringWithNullCheck(ExecState* exec, JSValue value) { if (value.isNull()) - return UString(); - return value.toString(exec); + return String(); + return ustringToString(value.toString(exec)); } -UString valueToStringWithUndefinedOrNullCheck(ExecState* exec, JSValue value) +String valueToStringWithUndefinedOrNullCheck(ExecState* exec, JSValue value) { if (value.isUndefinedOrNull()) - return UString(); - return value.toString(exec); + return String(); + return ustringToString(value.toString(exec)); } JSValue jsDateOrNull(ExecState* exec, double value) @@ -650,6 +533,9 @@ double valueToDate(ExecState* exec, JSValue value) void reportException(ExecState* exec, JSValue exception) { + if (exception.isObject() && asObject(exception)->exceptionType() == Terminated) + return; + UString errorMessage = exception.toString(exec); JSObject* exceptionObject = exception.toObject(exec); int lineNumber = exceptionObject->get(exec, Identifier(exec, "line")).toInt32(exec); @@ -657,7 +543,7 @@ void reportException(ExecState* exec, JSValue exception) exec->clearException(); if (ExceptionBase* exceptionBase = toExceptionBase(exception)) - errorMessage = exceptionBase->message() + ": " + exceptionBase->description(); + errorMessage = stringToUString(exceptionBase->message() + ": " + exceptionBase->description()); ScriptExecutionContext* scriptExecutionContext = static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->scriptExecutionContext(); ASSERT(scriptExecutionContext); @@ -667,7 +553,7 @@ void reportException(ExecState* exec, JSValue exception) if (!scriptExecutionContext) return; - scriptExecutionContext->reportException(errorMessage, lineNumber, exceptionSourceURL); + scriptExecutionContext->reportException(ustringToString(errorMessage), lineNumber, ustringToString(exceptionSourceURL)); } void reportCurrentException(ExecState* exec) @@ -747,6 +633,16 @@ bool shouldAllowNavigation(ExecState* exec, Frame* frame) return lexicalFrame && lexicalFrame->loader()->shouldAllowNavigation(frame); } +bool allowSettingSrcToJavascriptURL(ExecState* exec, Element* element, const String& name, const String& value) +{ + if ((element->hasTagName(iframeTag) || element->hasTagName(frameTag)) && equalIgnoringCase(name, "src") && protocolIsJavaScript(deprecatedParseURL(value))) { + Document* contentDocument = static_cast<HTMLFrameElementBase*>(element)->contentDocument(); + if (contentDocument && !checkNodeSecurity(exec, contentDocument)) + return false; + } + return true; +} + void printErrorMessageForFrame(Frame* frame, const String& message) { if (!frame) @@ -788,7 +684,7 @@ KURL completeURL(ExecState* exec, const String& relativeURL) return frame->loader()->completeURL(relativeURL); } -JSValue objectToStringFunctionGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot&) +JSValue objectToStringFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName) { return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), 0, propertyName, objectProtoFuncToString); } @@ -852,10 +748,4 @@ JSC::JSObject* toJSSequence(ExecState* exec, JSValue value, unsigned& length) return object; } -bool DOMObject::defineOwnProperty(ExecState* exec, const Identifier&, PropertyDescriptor&, bool) -{ - throwError(exec, TypeError, "defineProperty is not supported on DOM Objects"); - return false; -} - } // namespace WebCore diff --git a/WebCore/bindings/js/JSDOMBinding.h b/WebCore/bindings/js/JSDOMBinding.h index 807bf82..209be3f 100644 --- a/WebCore/bindings/js/JSDOMBinding.h +++ b/WebCore/bindings/js/JSDOMBinding.h @@ -23,6 +23,8 @@ #define JSDOMBinding_h #include "JSDOMGlobalObject.h" +#include "JSDOMWrapper.h" +#include "DOMWrapperWorld.h" #include "JSSVGContextCache.h" #include "Document.h" #include <runtime/Completion.h> @@ -52,21 +54,6 @@ namespace WebCore { class SVGElement; #endif - // Base class for all objects in this binding except Window. - class DOMObject : public JSC::JSObject { - protected: - explicit DOMObject(NonNullPassRefPtr<JSC::Structure> structure) - : JSObject(structure) - { - } - - virtual bool defineOwnProperty(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&, bool); - -#ifndef NDEBUG - virtual ~DOMObject(); -#endif - }; - // FIXME: This class should collapse into DOMObject once all DOMObjects are // updated to store a globalObject pointer. class DOMObjectWithGlobalPointer : public DOMObject { @@ -133,102 +120,6 @@ namespace WebCore { } }; - typedef JSC::WeakGCMap<void*, DOMObject*> DOMObjectWrapperMap; - typedef JSC::WeakGCMap<StringImpl*, JSC::JSString*> JSStringCache; - - class DOMWrapperWorld : public RefCounted<DOMWrapperWorld> { - public: - static PassRefPtr<DOMWrapperWorld> create(JSC::JSGlobalData* globalData, bool isNormal) - { - return adoptRef(new DOMWrapperWorld(globalData, isNormal)); - } - ~DOMWrapperWorld(); - - void rememberDocument(Document* document) { documentsWithWrappers.add(document); } - void forgetDocument(Document* document) { documentsWithWrappers.remove(document); } - - // FIXME: can we make this private? - DOMObjectWrapperMap m_wrappers; - JSStringCache m_stringCache; - - bool isNormal() const { return m_isNormal; } - - protected: - DOMWrapperWorld(JSC::JSGlobalData*, bool isNormal); - - private: - JSC::JSGlobalData* m_globalData; - HashSet<Document*> documentsWithWrappers; - bool m_isNormal; - }; - - // 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, public Noncopyable { - friend class JSGlobalDataWorldIterator; - - public: - WebCoreJSClientData(JSC::JSGlobalData* globalData) - : m_normalWorld(DOMWrapperWorld::create(globalData, true)) - { - m_worldSet.add(m_normalWorld.get()); - } - - virtual ~WebCoreJSClientData() - { - ASSERT(m_worldSet.contains(m_normalWorld.get())); - ASSERT(m_worldSet.size() == 1); - ASSERT(m_normalWorld->hasOneRef()); - m_normalWorld.clear(); - ASSERT(m_worldSet.isEmpty()); - } - - DOMWrapperWorld* normalWorld() { return m_normalWorld.get(); } - - void getAllWorlds(Vector<DOMWrapperWorld*>& worlds) - { - copyToVector(m_worldSet, worlds); - } - - 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: - HashSet<DOMWrapperWorld*> m_worldSet; - RefPtr<DOMWrapperWorld> m_normalWorld; - }; - DOMObject* getCachedDOMObjectWrapper(JSC::ExecState*, void* objectHandle); bool hasCachedDOMObjectWrapper(JSC::JSGlobalData*, void* objectHandle); void cacheDOMObjectWrapper(JSC::ExecState*, void* objectHandle, DOMObject* wrapper); @@ -237,8 +128,6 @@ namespace WebCore { JSNode* getCachedDOMNodeWrapper(JSC::ExecState*, Document*, Node*); void cacheDOMNodeWrapper(JSC::ExecState*, Document*, Node*, JSNode* wrapper); - void forgetAllDOMNodesForDocument(Document*); - void forgetWorldOfDOMNodesForDocument(Document*, DOMWrapperWorld*); void updateDOMNodeDocument(Node*, Document* oldDocument, Document* newDocument); void markDOMNodesForDocument(JSC::MarkStack&, Document*); @@ -253,12 +142,6 @@ 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* 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); @@ -375,8 +258,16 @@ namespace WebCore { // object, to let the engine know that collecting the JSString wrapper is unlikely to save memory. JSC::JSValue jsOwnedStringOrNull(JSC::ExecState*, const JSC::UString&); - JSC::UString valueToStringWithNullCheck(JSC::ExecState*, JSC::JSValue); // null if the value is null - JSC::UString valueToStringWithUndefinedOrNullCheck(JSC::ExecState*, JSC::JSValue); // null if the value is null or undefined + String identifierToString(const JSC::Identifier&); + String ustringToString(const JSC::UString&); + JSC::UString stringToUString(const String&); + + AtomicString identifierToAtomicString(const JSC::Identifier&); + AtomicString ustringToAtomicString(const JSC::UString&); + AtomicStringImpl* findAtomicString(const JSC::Identifier&); + + String valueToStringWithNullCheck(JSC::ExecState*, JSC::JSValue); // null if the value is null + String valueToStringWithUndefinedOrNullCheck(JSC::ExecState*, JSC::JSValue); // null if the value is null or undefined // Returns a Date instance for the specified value, or null if the value is NaN or infinity. JSC::JSValue jsDateOrNull(JSC::ExecState*, double); @@ -417,18 +308,15 @@ namespace WebCore { bool allowsAccessFromFrame(JSC::ExecState*, Frame*); bool allowsAccessFromFrame(JSC::ExecState*, Frame*, String& message); bool shouldAllowNavigation(JSC::ExecState*, Frame*); + bool allowSettingSrcToJavascriptURL(JSC::ExecState*, Element*, const String&, const String&); + void printErrorMessageForFrame(Frame*, const String& message); - JSC::JSValue objectToStringFunctionGetter(JSC::ExecState*, const JSC::Identifier& propertyName, const JSC::PropertySlot&); + JSC::JSValue objectToStringFunctionGetter(JSC::ExecState*, JSC::JSValue, const JSC::Identifier& propertyName); Frame* toLexicalFrame(JSC::ExecState*); Frame* toDynamicFrame(JSC::ExecState*); bool processingUserGesture(JSC::ExecState*); KURL completeURL(JSC::ExecState*, const String& relativeURL); - - inline DOMWrapperWorld* currentWorld(JSC::ExecState* exec) - { - return static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->world(); - } inline JSC::JSValue jsString(JSC::ExecState* exec, const String& s) { @@ -437,7 +325,7 @@ namespace WebCore { return jsEmptyString(exec); if (stringImpl->length() == 1 && stringImpl->characters()[0] <= 0xFF) - return jsString(exec, stringImpl->ustring()); + return jsString(exec, stringToUString(s)); JSStringCache& stringCache = currentWorld(exec)->m_stringCache; if (JSC::JSString* wrapper = stringCache.get(stringImpl)) @@ -446,6 +334,36 @@ namespace WebCore { return jsStringSlowCase(exec, stringCache, stringImpl); } + inline DOMObjectWrapperMap& domObjectWrapperMapFor(JSC::ExecState* exec) + { + return currentWorld(exec)->m_wrappers; + } + + inline String ustringToString(const JSC::UString& u) + { + return u.rep(); + } + + inline JSC::UString stringToUString(const String& s) + { + return JSC::UString(s.impl()); + } + + inline String identifierToString(const JSC::Identifier& i) + { + return i.ustring().rep(); + } + + inline AtomicString ustringToAtomicString(const JSC::UString& u) + { + return AtomicString(u.rep()); + } + + inline AtomicString identifierToAtomicString(const JSC::Identifier& identifier) + { + return AtomicString(identifier.ustring().rep()); + } + } // namespace WebCore #endif // JSDOMBinding_h diff --git a/WebCore/bindings/js/JSDOMFormDataCustom.cpp b/WebCore/bindings/js/JSDOMFormDataCustom.cpp new file mode 100644 index 0000000..830db6b --- /dev/null +++ b/WebCore/bindings/js/JSDOMFormDataCustom.cpp @@ -0,0 +1,56 @@ +/* + * 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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 "JSDOMFormData.h" + +#include "DOMFormData.h" +#include "JSBlob.h" +#include <runtime/Error.h> + +using namespace JSC; + +namespace WebCore { + +JSValue JSDOMFormData::append(ExecState* exec, const ArgList& args) +{ + if (args.size() >= 2) { + String name = ustringToString(args.at(0).toString(exec)); + JSValue value = args.at(1); + if (value.inherits(&JSBlob::s_info)) + impl()->append(name, toBlob(value)); + else + impl()->append(name, ustringToString(value.toString(exec))); + } + + return jsUndefined(); +} + +} // namespace WebCore diff --git a/WebCore/bindings/js/JSDOMWindowBase.cpp b/WebCore/bindings/js/JSDOMWindowBase.cpp index 4338cdd..82ac1ce 100644 --- a/WebCore/bindings/js/JSDOMWindowBase.cpp +++ b/WebCore/bindings/js/JSDOMWindowBase.cpp @@ -23,7 +23,6 @@ #include "config.h" #include "JSDOMWindowBase.h" -#include "CString.h" #include "Chrome.h" #include "Console.h" #include "DOMWindow.h" @@ -36,6 +35,9 @@ #include "ScriptController.h" #include "SecurityOrigin.h" #include "Settings.h" +#include "WebCoreJSClientData.h" +#include <wtf/Threading.h> +#include <wtf/text/CString.h> using namespace JSC; @@ -155,12 +157,12 @@ JSGlobalData* JSDOMWindowBase::commonJSGlobalData() static JSGlobalData* globalData = 0; if (!globalData) { - globalData = JSGlobalData::createLeaked().releaseRef(); + globalData = JSGlobalData::createLeaked(ThreadStackTypeLarge).releaseRef(); globalData->timeoutChecker.setTimeoutInterval(10000); // 10 seconds #ifndef NDEBUG - globalData->mainThreadOnly = true; + globalData->exclusiveThread = currentThread(); #endif - globalData->clientData = new WebCoreJSClientData(globalData); + initNormalWorldClientData(globalData); } return globalData; diff --git a/WebCore/bindings/js/JSDOMWindowCustom.cpp b/WebCore/bindings/js/JSDOMWindowCustom.cpp index bbd4a51..f5f2ae2 100644 --- a/WebCore/bindings/js/JSDOMWindowCustom.cpp +++ b/WebCore/bindings/js/JSDOMWindowCustom.cpp @@ -21,8 +21,8 @@ #include "JSDOMWindowCustom.h" #include "AtomicString.h" -#include "Base64.h" #include "Chrome.h" +#include "Database.h" #include "DOMWindow.h" #include "Document.h" #include "ExceptionCode.h" @@ -36,6 +36,8 @@ #include "HTMLDocument.h" #include "History.h" #include "JSAudioConstructor.h" +#include "JSDatabase.h" +#include "JSDatabaseCallback.h" #include "JSDOMWindowShell.h" #include "JSEvent.h" #include "JSEventListener.h" @@ -124,31 +126,31 @@ void JSDOMWindow::markChildren(MarkStack& markStack) } template<NativeFunction nativeFunction, int length> -JSValue nonCachingStaticFunctionGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot&) +JSValue nonCachingStaticFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName) { return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), length, propertyName, nativeFunction); } -static JSValue childFrameGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) +static JSValue childFrameGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName) { - return toJS(exec, static_cast<JSDOMWindow*>(asObject(slot.slotBase()))->impl()->frame()->tree()->child(AtomicString(propertyName))->domWindow()); + return toJS(exec, static_cast<JSDOMWindow*>(asObject(slotBase))->impl()->frame()->tree()->child(identifierToAtomicString(propertyName))->domWindow()); } -static JSValue indexGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) +static JSValue indexGetter(ExecState* exec, JSValue slotBase, unsigned index) { - return toJS(exec, static_cast<JSDOMWindow*>(asObject(slot.slotBase()))->impl()->frame()->tree()->child(slot.index())->domWindow()); + return toJS(exec, static_cast<JSDOMWindow*>(asObject(slotBase))->impl()->frame()->tree()->child(index)->domWindow()); } -static JSValue namedItemGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) +static JSValue namedItemGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName) { - JSDOMWindowBase* thisObj = static_cast<JSDOMWindow*>(asObject(slot.slotBase())); + JSDOMWindowBase* thisObj = static_cast<JSDOMWindow*>(asObject(slotBase)); Document* document = thisObj->impl()->frame()->document(); ASSERT(thisObj->allowsAccessFrom(exec)); ASSERT(document); ASSERT(document->isHTMLDocument()); - RefPtr<HTMLCollection> collection = document->windowNamedItems(propertyName); + RefPtr<HTMLCollection> collection = document->windowNamedItems(identifierToString(propertyName)); if (collection->length() == 1) return toJS(exec, collection->firstItem()); return toJS(exec, collection.get()); @@ -249,7 +251,7 @@ bool JSDOMWindow::getOwnPropertySlot(ExecState* exec, const Identifier& property // naming frames things that conflict with window properties that // are in Moz but not IE. Since we have some of these, we have to do // it the Moz way. - if (impl()->frame()->tree()->child(propertyName)) { + if (impl()->frame()->tree()->child(identifierToAtomicString(propertyName))) { slot.setCustom(this, childFrameGetter); return true; } @@ -287,7 +289,7 @@ bool JSDOMWindow::getOwnPropertySlot(ExecState* exec, const Identifier& property // Allow shortcuts like 'Image1' instead of document.images.Image1 Document* document = impl()->frame()->document(); if (document->isHTMLDocument()) { - AtomicStringImpl* atomicPropertyName = AtomicString::find(propertyName); + AtomicStringImpl* atomicPropertyName = findAtomicString(propertyName); if (atomicPropertyName && (static_cast<HTMLDocument*>(document)->hasNamedItem(atomicPropertyName) || document->hasElementWithId(atomicPropertyName))) { slot.setCustom(this, namedItemGetter); return true; @@ -338,7 +340,7 @@ bool JSDOMWindow::getOwnPropertyDescriptor(ExecState* exec, const Identifier& pr // naming frames things that conflict with window properties that // are in Moz but not IE. Since we have some of these, we have to do // it the Moz way. - if (impl()->frame()->tree()->child(propertyName)) { + if (impl()->frame()->tree()->child(identifierToAtomicString(propertyName))) { PropertySlot slot; slot.setCustom(this, childFrameGetter); descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum); @@ -357,7 +359,7 @@ bool JSDOMWindow::getOwnPropertyDescriptor(ExecState* exec, const Identifier& pr // Allow shortcuts like 'Image1' instead of document.images.Image1 Document* document = impl()->frame()->document(); if (document->isHTMLDocument()) { - AtomicStringImpl* atomicPropertyName = AtomicString::find(propertyName); + AtomicStringImpl* atomicPropertyName = findAtomicString(propertyName); if (atomicPropertyName && (static_cast<HTMLDocument*>(document)->hasNamedItem(atomicPropertyName) || document->hasElementWithId(atomicPropertyName))) { PropertySlot slot; slot.setCustom(this, namedItemGetter); @@ -504,7 +506,7 @@ void JSDOMWindow::setLocation(ExecState* exec, JSValue value) Frame* frame = impl()->frame(); ASSERT(frame); - KURL url = completeURL(exec, value.toString(exec)); + KURL url = completeURL(exec, ustringToString(value.toString(exec))); if (url.isNull()) return; @@ -666,12 +668,6 @@ static Frame* createWindow(ExecState* exec, Frame* lexicalFrame, Frame* dynamicF ASSERT(lexicalFrame); ASSERT(dynamicFrame); - if (Document* lexicalDocument = lexicalFrame->document()) { - // Sandboxed iframes cannot open new auxiliary browsing contexts. - if (lexicalDocument->securityOrigin()->isSandboxed(SandboxNavigation)) - return 0; - } - ResourceRequest request; // For whatever reason, Firefox uses the dynamicGlobalObject to determine @@ -729,7 +725,7 @@ static bool domWindowAllowPopUp(Frame* activeFrame, ExecState* exec) JSValue JSDOMWindow::open(ExecState* exec, const ArgList& args) { String urlString = valueToStringWithUndefinedOrNullCheck(exec, args.at(0)); - AtomicString frameName = args.at(1).isUndefinedOrNull() ? "_blank" : AtomicString(args.at(1).toString(exec)); + AtomicString frameName = args.at(1).isUndefinedOrNull() ? "_blank" : ustringToAtomicString(args.at(1).toString(exec)); WindowFeatures windowFeatures(valueToStringWithUndefinedOrNullCheck(exec, args.at(2))); Frame* frame = impl()->frame(); @@ -938,57 +934,6 @@ JSValue JSDOMWindow::setInterval(ExecState* exec, const ArgList& args) return jsNumber(exec, result); } -JSValue JSDOMWindow::atob(ExecState* exec, const ArgList& args) -{ - if (args.size() < 1) - return throwError(exec, SyntaxError, "Not enough arguments"); - - JSValue v = args.at(0); - if (v.isNull()) - return jsEmptyString(exec); - - UString s = v.toString(exec); - if (!s.is8Bit()) { - setDOMException(exec, INVALID_CHARACTER_ERR); - return jsUndefined(); - } - - Vector<char> in(s.size()); - for (unsigned i = 0; i < s.size(); ++i) - in[i] = static_cast<char>(s.data()[i]); - Vector<char> out; - - if (!base64Decode(in, out)) - return throwError(exec, GeneralError, "Cannot decode base64"); - - return jsString(exec, String(out.data(), out.size())); -} - -JSValue JSDOMWindow::btoa(ExecState* exec, const ArgList& args) -{ - if (args.size() < 1) - return throwError(exec, SyntaxError, "Not enough arguments"); - - JSValue v = args.at(0); - if (v.isNull()) - return jsEmptyString(exec); - - UString s = v.toString(exec); - if (!s.is8Bit()) { - setDOMException(exec, INVALID_CHARACTER_ERR); - return jsUndefined(); - } - - Vector<char> in(s.size()); - for (unsigned i = 0; i < s.size(); ++i) - in[i] = static_cast<char>(s.data()[i]); - Vector<char> out; - - base64Encode(in, out); - - return jsString(exec, String(out.data(), out.size())); -} - JSValue JSDOMWindow::addEventListener(ExecState* exec, const ArgList& args) { Frame* frame = impl()->frame(); @@ -999,7 +944,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), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); + impl()->addEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); return jsUndefined(); } @@ -1013,10 +958,31 @@ JSValue JSDOMWindow::removeEventListener(ExecState* exec, const ArgList& args) if (!listener.isObject()) return jsUndefined(); - impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); + impl()->removeEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); return jsUndefined(); } +#if ENABLE(DATABASE) +JSValue JSDOMWindow::openDatabase(ExecState* exec, const ArgList& args) +{ + if (!allowsAccessFrom(exec) || (args.size() < 4)) + return jsUndefined(); + ExceptionCode ec = 0; + const UString& name = args.at(0).toString(exec); + const UString& version = args.at(1).toString(exec); + const UString& displayName = args.at(2).toString(exec); + unsigned long estimatedSize = args.at(3).toInt32(exec); + RefPtr<DatabaseCallback> creationCallback; + if ((args.size() >= 5) && args.at(4).isObject()) + creationCallback = JSDatabaseCallback::create(asObject(args.at(4)), globalObject()); + + JSValue result = toJS(exec, globalObject(), WTF::getPtr(impl()->openDatabase(ustringToString(name), ustringToString(version), ustringToString(displayName), estimatedSize, creationCallback.release(), ec))); + + setDOMException(exec, ec); + return result; +} +#endif + DOMWindow* toDOMWindow(JSValue value) { if (!value.isObject()) diff --git a/WebCore/bindings/js/JSDOMWrapper.cpp b/WebCore/bindings/js/JSDOMWrapper.cpp new file mode 100644 index 0000000..3fcdcc1 --- /dev/null +++ b/WebCore/bindings/js/JSDOMWrapper.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2010 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. 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 "JSDOMWrapper.h" + +#include "JSDebugWrapperSet.h" +#include <runtime/Error.h> + +using namespace JSC; + +namespace WebCore { + +#ifndef NDEBUG + +DOMObject::~DOMObject() +{ + ASSERT(!JSDebugWrapperSet::shared().contains(this)); +} + +#endif + +bool DOMObject::defineOwnProperty(ExecState* exec, const Identifier&, PropertyDescriptor&, bool) +{ + throwError(exec, TypeError, "defineProperty is not supported on DOM Objects"); + return false; +} + +} // namespace WebCore diff --git a/WebCore/bindings/js/JSDOMWrapper.h b/WebCore/bindings/js/JSDOMWrapper.h new file mode 100644 index 0000000..00594cf --- /dev/null +++ b/WebCore/bindings/js/JSDOMWrapper.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2007 Samuel Weinig <sam@webkit.org> + * Copyright (C) 2009 Google, Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef JSDOMWrapper_h +#define JSDOMWrapper_h + +#include <runtime/JSObject.h> + +namespace WebCore { + +// Base class for all objects in this binding except Window. +class DOMObject : public JSC::JSObject { +protected: + explicit DOMObject(NonNullPassRefPtr<JSC::Structure> structure) + : JSObject(structure) + { + } + + virtual bool defineOwnProperty(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&, bool); + +#ifndef NDEBUG + virtual ~DOMObject(); +#endif +}; + +} // namespace WebCore + +#endif // JSDOMWrapper_h diff --git a/WebCore/bindings/js/JSDataGridColumnListCustom.cpp b/WebCore/bindings/js/JSDataGridColumnListCustom.cpp index 91b3d15..9a6982a 100644 --- a/WebCore/bindings/js/JSDataGridColumnListCustom.cpp +++ b/WebCore/bindings/js/JSDataGridColumnListCustom.cpp @@ -43,9 +43,9 @@ bool JSDataGridColumnList::canGetItemsForName(ExecState*, DataGridColumnList* im return impl->itemWithName(propertyName); } -JSValue JSDataGridColumnList::nameGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) +JSValue JSDataGridColumnList::nameGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName) { - JSDataGridColumnList* thisObj = static_cast<JSDataGridColumnList*>(asObject(slot.slotBase())); + JSDataGridColumnList* thisObj = static_cast<JSDataGridColumnList*>(asObject(slotBase)); return toJS(exec, thisObj->globalObject(), thisObj->impl()->itemWithName(propertyName)); } diff --git a/WebCore/bindings/js/JSDatabaseCallback.cpp b/WebCore/bindings/js/JSDatabaseCallback.cpp new file mode 100644 index 0000000..6887c86 --- /dev/null +++ b/WebCore/bindings/js/JSDatabaseCallback.cpp @@ -0,0 +1,83 @@ +/* + * 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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 "JSDatabaseCallback.h" + +#if ENABLE(DATABASE) + +#include "Frame.h" +#include "JSDatabase.h" +#include "ScriptExecutionContext.h" +#include <runtime/JSLock.h> +#include <wtf/MainThread.h> + +namespace WebCore { + +using namespace JSC; + +JSDatabaseCallback::JSDatabaseCallback(JSObject* callback, JSDOMGlobalObject* globalObject) + : m_data(new JSCallbackData(callback, globalObject)) + , m_isolatedWorld(globalObject->world()) +{ +} + +JSDatabaseCallback::~JSDatabaseCallback() +{ + callOnMainThread(JSCallbackData::deleteData, m_data); +#ifndef NDEBUG + m_data = 0; +#endif +} + +void JSDatabaseCallback::handleEvent(ScriptExecutionContext* context, Database* database) +{ + ASSERT(m_data); + ASSERT(context); + + RefPtr<JSDatabaseCallback> protect(this); + + JSC::JSLock lock(SilenceAssertionsOnly); + + JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(context, m_isolatedWorld.get()); + if (!globalObject) + return; + + ExecState* exec = globalObject->globalExec(); + MarkedArgumentBuffer args; + args.append(toJS(exec, database)); + + bool ignored; + m_data->invokeCallback(args, &ignored); +} + +} + +#endif // ENABLE(DATABASE) diff --git a/WebCore/bindings/js/JSDatabaseCallback.h b/WebCore/bindings/js/JSDatabaseCallback.h new file mode 100644 index 0000000..752a2c3 --- /dev/null +++ b/WebCore/bindings/js/JSDatabaseCallback.h @@ -0,0 +1,66 @@ +/* + * 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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 JSDatabaseCallback_h +#define JSDatabaseCallback_h + +#if ENABLE(DATABASE) + +#include "DatabaseCallback.h" +#include "JSCallbackData.h" +#include <wtf/Forward.h> + +namespace WebCore { + +class ScriptExecutionContext; + +class JSDatabaseCallback : public DatabaseCallback { +public: + static PassRefPtr<JSDatabaseCallback> create(JSC::JSObject* callback, JSDOMGlobalObject* globalObject) + { + return adoptRef(new JSDatabaseCallback(callback, globalObject)); + } + + virtual ~JSDatabaseCallback(); + + virtual void handleEvent(ScriptExecutionContext*, Database*); + +private: + JSDatabaseCallback(JSC::JSObject* callback, JSDOMGlobalObject*); + + JSCallbackData* m_data; + RefPtr<DOMWrapperWorld> m_isolatedWorld; +}; + +} + +#endif // ENABLE(DATABASE) + +#endif // JSDatabaseCallback_h diff --git a/WebCore/bindings/js/JSDatabaseCustom.cpp b/WebCore/bindings/js/JSDatabaseCustom.cpp index 0932cca..50f1d17 100644 --- a/WebCore/bindings/js/JSDatabaseCustom.cpp +++ b/WebCore/bindings/js/JSDatabaseCustom.cpp @@ -49,8 +49,8 @@ using namespace JSC; JSValue JSDatabase::changeVersion(ExecState* exec, const ArgList& args) { - String oldVersion = args.at(0).toString(exec); - String newVersion = args.at(1).toString(exec); + String oldVersion = ustringToString(args.at(0).toString(exec)); + String newVersion = ustringToString(args.at(1).toString(exec)); JSObject* object; if (!(object = args.at(2).getObject())) { diff --git a/WebCore/bindings/js/JSDebugWrapperSet.cpp b/WebCore/bindings/js/JSDebugWrapperSet.cpp new file mode 100644 index 0000000..b0d6ca9 --- /dev/null +++ b/WebCore/bindings/js/JSDebugWrapperSet.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2010 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. 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 "JSDebugWrapperSet.h" + +#include <wtf/StdLibExtras.h> + +#if ENABLE(WORKERS) +#include <wtf/ThreadSpecific.h> +#endif + +namespace WebCore { + +JSDebugWrapperSet& JSDebugWrapperSet::shared() +{ +#if ENABLE(WORKERS) + DEFINE_STATIC_LOCAL(WTF::ThreadSpecific<JSDebugWrapperSet>, staticWrapperSet, ()); + return *staticWrapperSet; +#else + DEFINE_STATIC_LOCAL(JSDebugWrapperSet, staticWrapperSet, ()); + return staticWrapperSet; +#endif +} + +JSDebugWrapperSet::JSDebugWrapperSet() +{ +} + +} // namespace WebCore diff --git a/WebCore/bindings/js/JSDebugWrapperSet.h b/WebCore/bindings/js/JSDebugWrapperSet.h new file mode 100644 index 0000000..94b6f78 --- /dev/null +++ b/WebCore/bindings/js/JSDebugWrapperSet.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2010 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. 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 JSDebugWrapperSet_h +#define JSDebugWrapperSet_h + +#include "JSDOMWrapper.h" +#include <wtf/HashSet.h> +#include <wtf/Noncopyable.h> + +namespace WebCore { + +// For debugging, keep a set of wrappers currently cached, and check that +// all are uncached before they are destroyed. This helps us catch bugs like: +// - wrappers being deleted without being removed from the cache +// - wrappers being cached twice + +class JSDebugWrapperSet : public Noncopyable { + friend class WTF::ThreadSpecific<JSDebugWrapperSet>; +public: + static JSDebugWrapperSet& shared(); + + void add(DOMObject* object) { m_wrapperSet.add(object); } + void remove(DOMObject* object) { m_wrapperSet.remove(object); } + bool contains(DOMObject* object) const { return m_wrapperSet.contains(object); } + + static void willCacheWrapper(DOMObject*); + static void didUncacheWrapper(DOMObject*); + +private: + JSDebugWrapperSet(); + + HashSet<DOMObject*> m_wrapperSet; +}; + +#ifdef NDEBUG + +inline void JSDebugWrapperSet::willCacheWrapper(DOMObject*) +{ +} + +inline void JSDebugWrapperSet::didUncacheWrapper(DOMObject*) +{ +} + +#else + +inline void JSDebugWrapperSet::willCacheWrapper(DOMObject* wrapper) +{ + ASSERT(!JSDebugWrapperSet::shared().contains(wrapper)); + JSDebugWrapperSet::shared().add(wrapper); +} + +inline void JSDebugWrapperSet::didUncacheWrapper(DOMObject* wrapper) +{ + if (!wrapper) + return; + ASSERT(JSDebugWrapperSet::shared().contains(wrapper)); + JSDebugWrapperSet::shared().remove(wrapper); +} + +#endif + +} // namespace WebCore + +#endif // JSDebugWrapperSet_h diff --git a/WebCore/bindings/js/JSDesktopNotificationsCustom.cpp b/WebCore/bindings/js/JSDesktopNotificationsCustom.cpp index 7485c1f..f86bae5 100644 --- a/WebCore/bindings/js/JSDesktopNotificationsCustom.cpp +++ b/WebCore/bindings/js/JSDesktopNotificationsCustom.cpp @@ -55,7 +55,7 @@ JSValue JSNotificationCenter::requestPermission(ExecState* exec, const ArgList& if (!args.at(0).isObject()) return throwError(exec, TypeError); - PassRefPtr<JSCustomVoidCallback> callback = JSCustomVoidCallback::create(args.at(0).getObject(), static_cast<Document*>(context)->frame()); + PassRefPtr<JSCustomVoidCallback> callback = JSCustomVoidCallback::create(args.at(0).getObject(), toJSDOMGlobalObject(static_cast<Document*>(context), exec)); impl()->requestPermission(callback); return jsUndefined(); @@ -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, currentWorld(exec)), args.at(2).toBoolean(exec)); + impl()->addEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, 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, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); + impl()->removeEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSDocumentCustom.cpp b/WebCore/bindings/js/JSDocumentCustom.cpp index eda153e..8abd8ce 100644 --- a/WebCore/bindings/js/JSDocumentCustom.cpp +++ b/WebCore/bindings/js/JSDocumentCustom.cpp @@ -79,7 +79,7 @@ void JSDocument::setLocation(ExecState* exec, JSValue value) if (!frame) return; - String str = value.toString(exec); + String str = ustringToString(value.toString(exec)); // IE and Mozilla both resolve the URL relative to the source frame, // not the target frame. diff --git a/WebCore/bindings/js/JSElementCustom.cpp b/WebCore/bindings/js/JSElementCustom.cpp index c725290..7e294bd 100644 --- a/WebCore/bindings/js/JSElementCustom.cpp +++ b/WebCore/bindings/js/JSElementCustom.cpp @@ -36,6 +36,7 @@ #include "HTMLFrameElementBase.h" #include "HTMLNames.h" #include "JSAttr.h" +#include "JSDOMBinding.h" #include "JSHTMLElementWrapperFactory.h" #include "JSNodeList.h" #include "NodeList.h" @@ -63,21 +64,11 @@ void JSElement::markChildren(MarkStack& markStack) markDOMObjectWrapper(markStack, globalData, static_cast<StyledElement*>(element)->inlineStyleDecl()); } -static inline bool allowSettingSrcToJavascriptURL(ExecState* exec, Element* element, const String& name, const String& value) -{ - if ((element->hasTagName(iframeTag) || element->hasTagName(frameTag)) && equalIgnoringCase(name, "src") && protocolIsJavaScript(deprecatedParseURL(value))) { - Document* contentDocument = static_cast<HTMLFrameElementBase*>(element)->contentDocument(); - if (contentDocument && !checkNodeSecurity(exec, contentDocument)) - return false; - } - return true; -} - JSValue JSElement::setAttribute(ExecState* exec, const ArgList& args) { ExceptionCode ec = 0; - AtomicString name = args.at(0).toString(exec); - AtomicString value = args.at(1).toString(exec); + AtomicString name = ustringToAtomicString(args.at(0).toString(exec)); + AtomicString value = ustringToAtomicString(args.at(1).toString(exec)); Element* imp = impl(); if (!allowSettingSrcToJavascriptURL(exec, imp, name, value)) @@ -110,8 +101,8 @@ JSValue JSElement::setAttributeNS(ExecState* exec, const ArgList& args) { ExceptionCode ec = 0; AtomicString namespaceURI = valueToStringWithNullCheck(exec, args.at(0)); - AtomicString qualifiedName = args.at(1).toString(exec); - AtomicString value = args.at(2).toString(exec); + AtomicString qualifiedName = ustringToAtomicString(args.at(1).toString(exec)); + AtomicString value = ustringToAtomicString(args.at(2).toString(exec)); Element* imp = impl(); if (!allowSettingSrcToJavascriptURL(exec, imp, qualifiedName, value)) diff --git a/WebCore/bindings/js/JSEventCustom.cpp b/WebCore/bindings/js/JSEventCustom.cpp index 04ceec5..6686d7a 100644 --- a/WebCore/bindings/js/JSEventCustom.cpp +++ b/WebCore/bindings/js/JSEventCustom.cpp @@ -31,9 +31,11 @@ #include "Clipboard.h" #include "CompositionEvent.h" +#include "CustomEvent.h" #include "Event.h" #include "JSBeforeLoadEvent.h" #include "JSClipboard.h" +#include "JSCustomEvent.h" #include "JSCompositionEvent.h" #include "JSErrorEvent.h" #include "JSKeyboardEvent.h" @@ -153,6 +155,8 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, Event* event) #endif else if (event->isPopStateEvent()) wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, PopStateEvent, event); + else if (event->isCustomEvent()) + wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, CustomEvent, event); 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 61f21be..3853cfc 100644 --- a/WebCore/bindings/js/JSEventListener.cpp +++ b/WebCore/bindings/js/JSEventListener.cpp @@ -83,7 +83,7 @@ void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext return; // FIXME: Is this check needed for other contexts? ScriptController* script = frame->script(); - if (!script->canExecuteScripts() || script->isPaused()) + if (!script->canExecuteScripts(AboutToExecuteScript) || script->isPaused()) return; } @@ -121,7 +121,7 @@ void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext reportCurrentException(exec); else { if (!retval.isUndefinedOrNull() && event->storesResultAsString()) - event->storeResult(retval.toString(exec)); + event->storeResult(ustringToString(retval.toString(exec))); if (m_isAttribute) { bool retvalbool; if (retval.getBoolean(retvalbool) && !retvalbool) @@ -129,53 +129,10 @@ void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext } } - if (scriptExecutionContext->isDocument()) - Document::updateStyleForAllDocuments(); deref(); } } -bool JSEventListener::reportError(ScriptExecutionContext* context, const String& message, const String& url, int lineNumber) -{ - JSLock lock(SilenceAssertionsOnly); - - JSObject* jsFunction = this->jsFunction(context); - if (!jsFunction) - return false; - - JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(context, m_isolatedWorld.get()); - ExecState* exec = globalObject->globalExec(); - - CallData callData; - CallType callType = jsFunction->getCallData(callData); - - if (callType == CallTypeNone) - return false; - - MarkedArgumentBuffer args; - args.append(jsString(exec, message)); - args.append(jsString(exec, url)); - args.append(jsNumber(exec, lineNumber)); - - JSGlobalData* globalData = globalObject->globalData(); - DynamicGlobalObjectScope globalObjectScope(exec, globalData->dynamicGlobalObject ? globalData->dynamicGlobalObject : globalObject); - - JSValue thisValue = globalObject->toThisObject(exec); - - globalData->timeoutChecker.start(); - JSValue returnValue = JSC::call(exec, jsFunction, callType, callData, thisValue, args); - globalData->timeoutChecker.stop(); - - // If an error occurs while handling the script error, it should be bubbled up. - if (exec->hadException()) { - exec->clearException(); - return false; - } - - bool bubbleEvent; - return returnValue.getBoolean(bubbleEvent) && !bubbleEvent; -} - bool JSEventListener::virtualisAttribute() const { return m_isAttribute; diff --git a/WebCore/bindings/js/JSEventListener.h b/WebCore/bindings/js/JSEventListener.h index 569c192..b15c589 100644 --- a/WebCore/bindings/js/JSEventListener.h +++ b/WebCore/bindings/js/JSEventListener.h @@ -60,7 +60,6 @@ namespace WebCore { virtual void markJSFunction(JSC::MarkStack&); virtual void invalidateJSFunction(JSC::JSObject*); virtual void handleEvent(ScriptExecutionContext*, Event*); - virtual bool reportError(ScriptExecutionContext*, const String& message, const String& url, int lineNumber); virtual bool virtualisAttribute() const; protected: diff --git a/WebCore/bindings/js/JSEventSourceConstructor.cpp b/WebCore/bindings/js/JSEventSourceConstructor.cpp index c6e4825..e48489b 100644 --- a/WebCore/bindings/js/JSEventSourceConstructor.cpp +++ b/WebCore/bindings/js/JSEventSourceConstructor.cpp @@ -71,7 +71,7 @@ static JSObject* constructEventSource(ExecState* exec, JSObject* constructor, co return throwError(exec, ReferenceError, "EventSource constructor associated document is unavailable"); ExceptionCode ec = 0; - RefPtr<EventSource> eventSource = EventSource::create(url, context, ec); + RefPtr<EventSource> eventSource = EventSource::create(ustringToString(url), context, ec); if (ec) { setDOMException(exec, ec); return 0; diff --git a/WebCore/bindings/js/JSEventSourceCustom.cpp b/WebCore/bindings/js/JSEventSourceCustom.cpp index dab3285..86db431 100644 --- a/WebCore/bindings/js/JSEventSourceCustom.cpp +++ b/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), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); + impl()->addEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, 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), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); + impl()->removeEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSGeolocationCustom.cpp b/WebCore/bindings/js/JSGeolocationCustom.cpp index 530b89b..8bc348c 100644 --- a/WebCore/bindings/js/JSGeolocationCustom.cpp +++ b/WebCore/bindings/js/JSGeolocationCustom.cpp @@ -26,6 +26,8 @@ #include "config.h" #include "JSGeolocation.h" +#if ENABLE(GEOLOCATION) + #include "DOMWindow.h" #include "ExceptionCode.h" #include "Geolocation.h" @@ -178,3 +180,5 @@ JSValue JSGeolocation::watchPosition(ExecState* exec, const ArgList& args) } } // namespace WebCore + +#endif // ENABLE(GEOLOCATION) diff --git a/WebCore/bindings/js/JSHTMLAllCollectionCustom.cpp b/WebCore/bindings/js/JSHTMLAllCollectionCustom.cpp index fd1dd11..86d6fa2 100644 --- a/WebCore/bindings/js/JSHTMLAllCollectionCustom.cpp +++ b/WebCore/bindings/js/JSHTMLAllCollectionCustom.cpp @@ -43,7 +43,7 @@ namespace WebCore { static JSValue getNamedItems(ExecState* exec, JSHTMLAllCollection* collection, const Identifier& propertyName) { Vector<RefPtr<Node> > namedItems; - collection->impl()->namedItems(propertyName, namedItems); + collection->impl()->namedItems(identifierToAtomicString(propertyName), namedItems); if (namedItems.isEmpty()) return jsUndefined(); @@ -86,7 +86,7 @@ static JSValue JSC_HOST_CALL callHTMLAllCollection(ExecState* exec, JSObject* fu UString string = args.at(0).toString(exec); unsigned index = args.at(1).toString(exec).toUInt32(&ok, false); if (ok) { - String pstr = string; + String pstr = ustringToString(string); Node* node = collection->namedItem(pstr); while (node) { if (!index) @@ -108,13 +108,13 @@ CallType JSHTMLAllCollection::getCallData(CallData& callData) bool JSHTMLAllCollection::canGetItemsForName(ExecState*, HTMLAllCollection* collection, const Identifier& propertyName) { Vector<RefPtr<Node> > namedItems; - collection->namedItems(propertyName, namedItems); + collection->namedItems(identifierToAtomicString(propertyName), namedItems); return !namedItems.isEmpty(); } -JSValue JSHTMLAllCollection::nameGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) +JSValue JSHTMLAllCollection::nameGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName) { - JSHTMLAllCollection* thisObj = static_cast<JSHTMLAllCollection*>(asObject(slot.slotBase())); + JSHTMLAllCollection* thisObj = static_cast<JSHTMLAllCollection*>(asObject(slotBase)); return getNamedItems(exec, thisObj, propertyName); } diff --git a/WebCore/bindings/js/JSHTMLAppletElementCustom.cpp b/WebCore/bindings/js/JSHTMLAppletElementCustom.cpp index 30892e0..40d20cf 100644 --- a/WebCore/bindings/js/JSHTMLAppletElementCustom.cpp +++ b/WebCore/bindings/js/JSHTMLAppletElementCustom.cpp @@ -53,14 +53,4 @@ CallType JSHTMLAppletElement::getCallData(CallData& callData) return runtimeObjectGetCallData(impl(), callData); } -bool JSHTMLAppletElement::canGetItemsForName(ExecState*, HTMLAppletElement*, const Identifier& propertyName) -{ - return propertyName == "__apple_runtime_object"; -} - -JSValue JSHTMLAppletElement::nameGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) -{ - return runtimeObjectGetter(exec, propertyName, slot); -} - } // namespace WebCore diff --git a/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp b/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp index 80634f7..89f62f8 100644 --- a/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp +++ b/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp @@ -78,7 +78,7 @@ JSValue JSHTMLCanvasElement::getContext(ExecState* exec, const ArgList& args) } } #endif - return toJS(exec, globalObject(), WTF::getPtr(canvas->getContext(contextId, attrs.get()))); + return toJS(exec, globalObject(), WTF::getPtr(canvas->getContext(ustringToString(contextId), attrs.get()))); } } // namespace WebCore diff --git a/WebCore/bindings/js/JSHTMLCollectionCustom.cpp b/WebCore/bindings/js/JSHTMLCollectionCustom.cpp index ba61922..c5eb41a 100644 --- a/WebCore/bindings/js/JSHTMLCollectionCustom.cpp +++ b/WebCore/bindings/js/JSHTMLCollectionCustom.cpp @@ -40,7 +40,7 @@ namespace WebCore { static JSValue getNamedItems(ExecState* exec, JSHTMLCollection* collection, const Identifier& propertyName) { Vector<RefPtr<Node> > namedItems; - collection->impl()->namedItems(propertyName, namedItems); + collection->impl()->namedItems(identifierToAtomicString(propertyName), namedItems); if (namedItems.isEmpty()) return jsUndefined(); @@ -83,7 +83,7 @@ static JSValue JSC_HOST_CALL callHTMLCollection(ExecState* exec, JSObject* funct UString string = args.at(0).toString(exec); unsigned index = args.at(1).toString(exec).toUInt32(&ok, false); if (ok) { - String pstr = string; + String pstr = ustringToString(string); Node* node = collection->namedItem(pstr); while (node) { if (!index) @@ -105,13 +105,13 @@ CallType JSHTMLCollection::getCallData(CallData& callData) bool JSHTMLCollection::canGetItemsForName(ExecState*, HTMLCollection* collection, const Identifier& propertyName) { Vector<RefPtr<Node> > namedItems; - collection->namedItems(propertyName, namedItems); + collection->namedItems(identifierToAtomicString(propertyName), namedItems); return !namedItems.isEmpty(); } -JSValue JSHTMLCollection::nameGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) +JSValue JSHTMLCollection::nameGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName) { - JSHTMLCollection* thisObj = static_cast<JSHTMLCollection*>(asObject(slot.slotBase())); + JSHTMLCollection* thisObj = static_cast<JSHTMLCollection*>(asObject(slotBase)); return getNamedItems(exec, thisObj, propertyName); } diff --git a/WebCore/bindings/js/JSHTMLDocumentCustom.cpp b/WebCore/bindings/js/JSHTMLDocumentCustom.cpp index 7fde002..de0e96f 100644 --- a/WebCore/bindings/js/JSHTMLDocumentCustom.cpp +++ b/WebCore/bindings/js/JSHTMLDocumentCustom.cpp @@ -51,16 +51,16 @@ using namespace HTMLNames; bool JSHTMLDocument::canGetItemsForName(ExecState*, HTMLDocument* document, const Identifier& propertyName) { - AtomicStringImpl* atomicPropertyName = AtomicString::find(propertyName); + AtomicStringImpl* atomicPropertyName = findAtomicString(propertyName); return atomicPropertyName && (document->hasNamedItem(atomicPropertyName) || document->hasExtraNamedItem(atomicPropertyName)); } -JSValue JSHTMLDocument::nameGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) +JSValue JSHTMLDocument::nameGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName) { - JSHTMLDocument* thisObj = static_cast<JSHTMLDocument*>(asObject(slot.slotBase())); + JSHTMLDocument* thisObj = static_cast<JSHTMLDocument*>(asObject(slotBase)); HTMLDocument* document = static_cast<HTMLDocument*>(thisObj->impl()); - String name = propertyName; + String name = identifierToString(propertyName); RefPtr<HTMLCollection> collection = document->documentNamedItems(name); unsigned length = collection->length(); @@ -137,14 +137,14 @@ static inline void documentWrite(ExecState* exec, const ArgList& args, HTMLDocum size_t size = args.size(); UString firstString = args.at(0).toString(exec); - SegmentedString segmentedString = String(firstString); + SegmentedString segmentedString = ustringToString(firstString); if (size != 1) { if (!size) segmentedString.clear(); else { for (size_t i = 1; i < size; ++i) { UString subsequentString = args.at(i).toString(exec); - segmentedString.append(SegmentedString(String(subsequentString))); + segmentedString.append(SegmentedString(ustringToString(subsequentString))); } } } diff --git a/WebCore/bindings/js/JSHTMLEmbedElementCustom.cpp b/WebCore/bindings/js/JSHTMLEmbedElementCustom.cpp index bce3ffb..b9f8c12 100644 --- a/WebCore/bindings/js/JSHTMLEmbedElementCustom.cpp +++ b/WebCore/bindings/js/JSHTMLEmbedElementCustom.cpp @@ -53,14 +53,4 @@ CallType JSHTMLEmbedElement::getCallData(CallData& callData) return runtimeObjectGetCallData(impl(), callData); } -bool JSHTMLEmbedElement::canGetItemsForName(ExecState*, HTMLEmbedElement*, const Identifier& propertyName) -{ - return propertyName == "__apple_runtime_object"; -} - -JSValue JSHTMLEmbedElement::nameGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) -{ - return runtimeObjectGetter(exec, propertyName, slot); -} - } // namespace WebCore diff --git a/WebCore/bindings/js/JSHTMLFormElementCustom.cpp b/WebCore/bindings/js/JSHTMLFormElementCustom.cpp index c364c14..2e7522c 100644 --- a/WebCore/bindings/js/JSHTMLFormElementCustom.cpp +++ b/WebCore/bindings/js/JSHTMLFormElementCustom.cpp @@ -40,17 +40,17 @@ namespace WebCore { bool JSHTMLFormElement::canGetItemsForName(ExecState*, HTMLFormElement* form, const Identifier& propertyName) { Vector<RefPtr<Node> > namedItems; - form->getNamedElements(propertyName, namedItems); + form->getNamedElements(identifierToAtomicString(propertyName), namedItems); return namedItems.size(); } -JSValue JSHTMLFormElement::nameGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) +JSValue JSHTMLFormElement::nameGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName) { - JSHTMLElement* jsForm = static_cast<JSHTMLFormElement*>(asObject(slot.slotBase())); + JSHTMLElement* jsForm = static_cast<JSHTMLFormElement*>(asObject(slotBase)); HTMLFormElement* form = static_cast<HTMLFormElement*>(jsForm->impl()); Vector<RefPtr<Node> > namedItems; - form->getNamedElements(propertyName, namedItems); + form->getNamedElements(identifierToAtomicString(propertyName), namedItems); if (namedItems.isEmpty()) return jsUndefined(); diff --git a/WebCore/bindings/js/JSHTMLFrameSetElementCustom.cpp b/WebCore/bindings/js/JSHTMLFrameSetElementCustom.cpp index 68769d6..617aaff 100644 --- a/WebCore/bindings/js/JSHTMLFrameSetElementCustom.cpp +++ b/WebCore/bindings/js/JSHTMLFrameSetElementCustom.cpp @@ -43,16 +43,16 @@ using namespace HTMLNames; bool JSHTMLFrameSetElement::canGetItemsForName(ExecState*, HTMLFrameSetElement* frameSet, const Identifier& propertyName) { - Node* frame = frameSet->children()->namedItem(propertyName); + Node* frame = frameSet->children()->namedItem(identifierToAtomicString(propertyName)); return frame && frame->hasTagName(frameTag); } -JSValue JSHTMLFrameSetElement::nameGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) +JSValue JSHTMLFrameSetElement::nameGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName) { - JSHTMLElement* thisObj = static_cast<JSHTMLElement*>(asObject(slot.slotBase())); + JSHTMLElement* thisObj = static_cast<JSHTMLElement*>(asObject(slotBase)); HTMLElement* element = static_cast<HTMLElement*>(thisObj->impl()); - Node* frame = element->children()->namedItem(propertyName); + Node* frame = element->children()->namedItem(identifierToAtomicString(propertyName)); if (Document* doc = static_cast<HTMLFrameElement*>(frame)->contentDocument()) { if (JSDOMWindowShell* window = toJSDOMWindowShell(doc->frame(), currentWorld(exec))) return window; diff --git a/WebCore/bindings/js/JSHTMLObjectElementCustom.cpp b/WebCore/bindings/js/JSHTMLObjectElementCustom.cpp index 1bfb51f..68c9e59 100644 --- a/WebCore/bindings/js/JSHTMLObjectElementCustom.cpp +++ b/WebCore/bindings/js/JSHTMLObjectElementCustom.cpp @@ -53,14 +53,4 @@ CallType JSHTMLObjectElement::getCallData(CallData& callData) return runtimeObjectGetCallData(impl(), callData); } -bool JSHTMLObjectElement::canGetItemsForName(ExecState*, HTMLObjectElement*, const Identifier& propertyName) -{ - return propertyName == "__apple_runtime_object"; -} - -JSValue JSHTMLObjectElement::nameGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) -{ - return runtimeObjectGetter(exec, propertyName, slot); -} - } // namespace WebCore diff --git a/WebCore/bindings/js/JSHistoryCustom.cpp b/WebCore/bindings/js/JSHistoryCustom.cpp index fff747f..c031b30 100644 --- a/WebCore/bindings/js/JSHistoryCustom.cpp +++ b/WebCore/bindings/js/JSHistoryCustom.cpp @@ -38,17 +38,17 @@ using namespace JSC; namespace WebCore { -static JSValue nonCachingStaticBackFunctionGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot&) +static JSValue nonCachingStaticBackFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName) { return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), 0, propertyName, jsHistoryPrototypeFunctionBack); } -static JSValue nonCachingStaticForwardFunctionGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot&) +static JSValue nonCachingStaticForwardFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName) { return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), 0, propertyName, jsHistoryPrototypeFunctionForward); } -static JSValue nonCachingStaticGoFunctionGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot&) +static JSValue nonCachingStaticGoFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName) { return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), 1, propertyName, jsHistoryPrototypeFunctionGo); } diff --git a/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp b/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp index 3db894d..8bfb8a3 100644 --- a/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp +++ b/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp @@ -1,7 +1,7 @@ /* * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com> - * Copyright (C) 2009 Google Inc. All rights reserved. + * 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 @@ -48,6 +48,7 @@ #include "InspectorController.h" #include "InspectorResource.h" #include "JSDOMWindow.h" +#include "JSDOMWindowCustom.h" #include "JSNode.h" #include "JSRange.h" #include "Node.h" @@ -67,17 +68,17 @@ #if ENABLE(JAVASCRIPT_DEBUGGER) #include "JavaScriptCallFrame.h" -#include "JavaScriptDebugServer.h" #include "JSJavaScriptCallFrame.h" +#include "ScriptDebugServer.h" #endif using namespace JSC; namespace WebCore { -static ScriptObject createInjectedScript(const String& source, InjectedScriptHost* injectedScriptHost, ScriptState* scriptState, long id) +ScriptObject InjectedScriptHost::createInjectedScript(const String& source, ScriptState* scriptState, long id) { - SourceCode sourceCode = makeSource(source); + SourceCode sourceCode = makeSource(stringToUString(source)); JSLock lock(SilenceAssertionsOnly); JSDOMGlobalObject* globalObject = static_cast<JSDOMGlobalObject*>(scriptState->lexicalGlobalObject()); JSValue globalThisValue = scriptState->globalThisValue(); @@ -91,9 +92,10 @@ static ScriptObject createInjectedScript(const String& source, InjectedScriptHos return ScriptObject(); MarkedArgumentBuffer args; - args.append(toJS(scriptState, globalObject, injectedScriptHost)); + args.append(toJS(scriptState, globalObject, this)); args.append(globalThisValue); args.append(jsNumber(scriptState, id)); + args.append(jsString(scriptState, String("JSC"))); JSValue result = JSC::call(scriptState, functionValue, callType, callData, globalThisValue, args); if (result.isObject()) return ScriptObject(scriptState, result.getObject()); @@ -118,10 +120,9 @@ JSValue JSInjectedScriptHost::databaseForId(ExecState* exec, const ArgList& args #endif #if ENABLE(JAVASCRIPT_DEBUGGER) - JSValue JSInjectedScriptHost::currentCallFrame(ExecState* exec, const ArgList&) { - JavaScriptCallFrame* callFrame = impl()->currentCallFrame(); + JavaScriptCallFrame* callFrame = ScriptDebugServer::shared().currentCallFrame(); if (!callFrame || !callFrame->isValid()) return jsUndefined(); @@ -134,7 +135,6 @@ JSValue JSInjectedScriptHost::isActivation(ExecState*, const ArgList& args) JSObject* object = args.at(0).getObject(); return jsBoolean(object && object->isActivationObject()); } - #endif JSValue JSInjectedScriptHost::nodeForId(ExecState* exec, const ArgList& args) @@ -223,15 +223,23 @@ InjectedScript InjectedScriptHost::injectedScriptFor(ScriptState* scriptState) if (injectedScript) return InjectedScript(ScriptObject(scriptState, injectedScript)); - ASSERT(!m_injectedScriptSource.isEmpty()); - ScriptObject injectedScriptObject = createInjectedScript(m_injectedScriptSource, this, scriptState, m_nextInjectedScriptId); - globalObject->setInjectedScript(injectedScriptObject.jsObject()); - InjectedScript result(injectedScriptObject); - m_idToInjectedScript.set(m_nextInjectedScriptId, result); - m_nextInjectedScriptId++; + ASSERT(!m_injectedScriptSource.isEmpty()); + pair<long, ScriptObject> injectedScriptObject = injectScript(m_injectedScriptSource, scriptState); + globalObject->setInjectedScript(injectedScriptObject.second.jsObject()); + InjectedScript result(injectedScriptObject.second); + m_idToInjectedScript.set(injectedScriptObject.first, result); return result; } +bool InjectedScriptHost::canAccessInspectedWindow(ScriptState* scriptState) +{ + JSLock lock(SilenceAssertionsOnly); + JSDOMWindow* inspectedWindow = toJSDOMWindow(scriptState->lexicalGlobalObject()); + if (!inspectedWindow) + return false; + return inspectedWindow->allowsAccessFromNoErrorMessage(scriptState); +} + } // namespace WebCore #endif // ENABLE(INSPECTOR) diff --git a/WebCore/bindings/js/JSInspectorFrontendHostCustom.cpp b/WebCore/bindings/js/JSInspectorFrontendHostCustom.cpp index 7b06bac..d18260b 100644 --- a/WebCore/bindings/js/JSInspectorFrontendHostCustom.cpp +++ b/WebCore/bindings/js/JSInspectorFrontendHostCustom.cpp @@ -49,11 +49,39 @@ using namespace JSC; namespace WebCore { +JSValue JSInspectorFrontendHost::platform(ExecState* execState, const ArgList&) +{ +#if PLATFORM(MAC) + DEFINE_STATIC_LOCAL(const String, platform, ("mac")); +#elif OS(WINDOWS) + DEFINE_STATIC_LOCAL(const String, platform, ("windows")); +#elif OS(LINUX) + DEFINE_STATIC_LOCAL(const String, platform, ("linux")); +#else + DEFINE_STATIC_LOCAL(const String, platform, ("unknown")); +#endif + return jsString(execState, platform); +} + +JSValue JSInspectorFrontendHost::port(ExecState* execState, const ArgList&) +{ +#if PLATFORM(QT) + DEFINE_STATIC_LOCAL(const String, port, ("qt")); +#elif PLATFORM(GTK) + DEFINE_STATIC_LOCAL(const String, port, ("gtk")); +#elif PLATFORM(WX) + DEFINE_STATIC_LOCAL(const String, port, ("wx")); +#else + DEFINE_STATIC_LOCAL(const String, port, ("unknown")); +#endif + return jsString(execState, port); +} + JSValue JSInspectorFrontendHost::showContextMenu(ExecState* execState, const ArgList& args) { if (args.size() < 2) return jsUndefined(); - +#if ENABLE(CONTEXT_MENUS) Event* event = toEvent(args.at(0)); JSArray* array = asArray(args.at(1)); @@ -67,11 +95,14 @@ JSValue JSInspectorFrontendHost::showContextMenu(ExecState* execState, const Arg items.append(new ContextMenuItem(SeparatorType, ContextMenuItemTagNoAction, String())); else { ContextMenuAction typedId = static_cast<ContextMenuAction>(ContextMenuItemBaseCustomTag + id.toInt32(execState)); - items.append(new ContextMenuItem(ActionType, typedId, label.toString(execState))); + items.append(new ContextMenuItem(ActionType, typedId, ustringToString(label.toString(execState)))); } } impl()->showContextMenu(event, items); +#else + UNUSED_PARAM(execState); +#endif return jsUndefined(); } diff --git a/WebCore/bindings/js/JSJavaScriptCallFrameCustom.cpp b/WebCore/bindings/js/JSJavaScriptCallFrameCustom.cpp index afbdf5d..080f730 100644 --- a/WebCore/bindings/js/JSJavaScriptCallFrameCustom.cpp +++ b/WebCore/bindings/js/JSJavaScriptCallFrameCustom.cpp @@ -85,6 +85,12 @@ JSValue JSJavaScriptCallFrame::scopeChain(ExecState* exec) const return constructArray(exec, list); } +JSValue JSJavaScriptCallFrame::scopeType(ExecState*, const ArgList&) +{ + // FIXME(37663): implement this method the way it's done in the InjectedScipt.js + return jsNull(); +} + } // namespace WebCore #endif // ENABLE(JAVASCRIPT_DEBUGGER) diff --git a/WebCore/bindings/js/JSLazyEventListener.cpp b/WebCore/bindings/js/JSLazyEventListener.cpp index 4fbdaa6..1aad7df 100644 --- a/WebCore/bindings/js/JSLazyEventListener.cpp +++ b/WebCore/bindings/js/JSLazyEventListener.cpp @@ -79,7 +79,7 @@ JSObject* JSLazyEventListener::initializeJSFunction(ScriptExecutionContext* exec return 0; ScriptController* scriptController = frame->script(); - if (!scriptController->canExecuteScripts()) + if (!scriptController->canExecuteScripts(AboutToExecuteScript)) return 0; JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(executionContext, isolatedWorld()); @@ -93,17 +93,17 @@ JSObject* JSLazyEventListener::initializeJSFunction(ScriptExecutionContext* exec return 0; // FIXME: Is this check needed for non-Document contexts? ScriptController* script = frame->script(); - if (!script->canExecuteScripts() || script->isPaused()) + if (!script->canExecuteScripts(AboutToExecuteScript) || script->isPaused()) return 0; } ExecState* exec = globalObject->globalExec(); MarkedArgumentBuffer args; - args.append(jsNontrivialString(exec, m_eventParameterName)); + args.append(jsNontrivialString(exec, stringToUString(m_eventParameterName))); args.append(jsString(exec, m_code)); - JSObject* jsFunction = constructFunction(exec, args, Identifier(exec, m_functionName), m_sourceURL, m_lineNumber); // FIXME: is globalExec ok? + JSObject* jsFunction = constructFunction(exec, args, Identifier(exec, stringToUString(m_functionName)), stringToUString(m_sourceURL), m_lineNumber); // FIXME: is globalExec ok? if (exec->hadException()) { exec->clearException(); return 0; diff --git a/WebCore/bindings/js/JSLocationCustom.cpp b/WebCore/bindings/js/JSLocationCustom.cpp index 8599242..e92a750 100644 --- a/WebCore/bindings/js/JSLocationCustom.cpp +++ b/WebCore/bindings/js/JSLocationCustom.cpp @@ -39,17 +39,17 @@ using namespace JSC; namespace WebCore { -static JSValue nonCachingStaticReplaceFunctionGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot&) +static JSValue nonCachingStaticReplaceFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName) { return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), 1, propertyName, jsLocationPrototypeFunctionReplace); } -static JSValue nonCachingStaticReloadFunctionGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot&) +static JSValue nonCachingStaticReloadFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName) { return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), 0, propertyName, jsLocationPrototypeFunctionReload); } -static JSValue nonCachingStaticAssignFunctionGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot&) +static JSValue nonCachingStaticAssignFunctionGetter(ExecState* exec, JSValue, const Identifier& propertyName) { return new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), 1, propertyName, jsLocationPrototypeFunctionAssign); } @@ -199,7 +199,7 @@ void JSLocation::setHref(ExecState* exec, JSValue value) Frame* frame = impl()->frame(); ASSERT(frame); - KURL url = completeURL(exec, value.toString(exec)); + KURL url = completeURL(exec, ustringToString(value.toString(exec))); if (url.isNull()) return; @@ -215,7 +215,7 @@ void JSLocation::setProtocol(ExecState* exec, JSValue value) ASSERT(frame); KURL url = frame->loader()->url(); - if (!url.setProtocol(value.toString(exec))) { + if (!url.setProtocol(ustringToString(value.toString(exec)))) { setDOMException(exec, SYNTAX_ERR); return; } @@ -229,7 +229,7 @@ void JSLocation::setHost(ExecState* exec, JSValue value) ASSERT(frame); KURL url = frame->loader()->url(); - url.setHostAndPort(value.toString(exec)); + url.setHostAndPort(ustringToString(value.toString(exec))); navigateIfAllowed(exec, frame, url, !frame->script()->anyPageIsProcessingUserGesture(), false); } @@ -240,7 +240,7 @@ void JSLocation::setHostname(ExecState* exec, JSValue value) ASSERT(frame); KURL url = frame->loader()->url(); - url.setHost(value.toString(exec)); + url.setHost(ustringToString(value.toString(exec))); navigateIfAllowed(exec, frame, url, !frame->script()->anyPageIsProcessingUserGesture(), false); } @@ -268,7 +268,7 @@ void JSLocation::setPathname(ExecState* exec, JSValue value) ASSERT(frame); KURL url = frame->loader()->url(); - url.setPath(value.toString(exec)); + url.setPath(ustringToString(value.toString(exec))); navigateIfAllowed(exec, frame, url, !frame->script()->anyPageIsProcessingUserGesture(), false); } @@ -279,7 +279,7 @@ void JSLocation::setSearch(ExecState* exec, JSValue value) ASSERT(frame); KURL url = frame->loader()->url(); - url.setQuery(value.toString(exec)); + url.setQuery(ustringToString(value.toString(exec))); navigateIfAllowed(exec, frame, url, !frame->script()->anyPageIsProcessingUserGesture(), false); } @@ -291,7 +291,7 @@ void JSLocation::setHash(ExecState* exec, JSValue value) KURL url = frame->loader()->url(); String oldFragmentIdentifier = url.fragmentIdentifier(); - String str = value.toString(exec); + String str = ustringToString(value.toString(exec)); if (str.startsWith("#")) str = str.substring(1); if (equalIgnoringNullity(oldFragmentIdentifier, str)) @@ -307,7 +307,7 @@ JSValue JSLocation::replace(ExecState* exec, const ArgList& args) if (!frame) return jsUndefined(); - KURL url = completeURL(exec, args.at(0).toString(exec)); + KURL url = completeURL(exec, ustringToString(args.at(0).toString(exec))); if (url.isNull()) return jsUndefined(); @@ -335,7 +335,7 @@ JSValue JSLocation::assign(ExecState* exec, const ArgList& args) if (!frame) return jsUndefined(); - KURL url = completeURL(exec, args.at(0).toString(exec)); + KURL url = completeURL(exec, ustringToString(args.at(0).toString(exec))); if (url.isNull()) return jsUndefined(); diff --git a/WebCore/bindings/js/JSMessageEventCustom.cpp b/WebCore/bindings/js/JSMessageEventCustom.cpp index 2e7b2d0..fc1f542 100644 --- a/WebCore/bindings/js/JSMessageEventCustom.cpp +++ b/WebCore/bindings/js/JSMessageEventCustom.cpp @@ -72,7 +72,7 @@ JSC::JSValue JSMessageEvent::initMessageEvent(JSC::ExecState* exec, const JSC::A } MessageEvent* event = static_cast<MessageEvent*>(this->impl()); - event->initMessageEvent(typeArg, canBubbleArg, cancelableArg, dataArg, originArg, lastEventIdArg, sourceArg, messagePorts.release()); + event->initMessageEvent(ustringToAtomicString(typeArg), canBubbleArg, cancelableArg, dataArg, ustringToString(originArg), ustringToString(lastEventIdArg), sourceArg, messagePorts.release()); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSMessagePortCustom.cpp b/WebCore/bindings/js/JSMessagePortCustom.cpp index 2ee8125..f7c0160 100644 --- a/WebCore/bindings/js/JSMessagePortCustom.cpp +++ b/WebCore/bindings/js/JSMessagePortCustom.cpp @@ -58,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), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); + impl()->addEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); return jsUndefined(); } @@ -68,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), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); + impl()->removeEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSMimeTypeArrayCustom.cpp b/WebCore/bindings/js/JSMimeTypeArrayCustom.cpp index c90dadd..bdd6ddb 100644 --- a/WebCore/bindings/js/JSMimeTypeArrayCustom.cpp +++ b/WebCore/bindings/js/JSMimeTypeArrayCustom.cpp @@ -30,13 +30,13 @@ using namespace JSC; bool JSMimeTypeArray::canGetItemsForName(ExecState*, MimeTypeArray* mimeTypeArray, const Identifier& propertyName) { - return mimeTypeArray->canGetItemsForName(propertyName); + return mimeTypeArray->canGetItemsForName(identifierToAtomicString(propertyName)); } -JSValue JSMimeTypeArray::nameGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) +JSValue JSMimeTypeArray::nameGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName) { - JSMimeTypeArray* thisObj = static_cast<JSMimeTypeArray*>(asObject(slot.slotBase())); - return toJS(exec, thisObj->impl()->namedItem(propertyName)); + JSMimeTypeArray* thisObj = static_cast<JSMimeTypeArray*>(asObject(slotBase)); + return toJS(exec, thisObj->impl()->namedItem(identifierToAtomicString(propertyName))); } } // namespace WebCore diff --git a/WebCore/bindings/js/JSNamedNodeMapCustom.cpp b/WebCore/bindings/js/JSNamedNodeMapCustom.cpp index d1bbeec..e1c490e 100644 --- a/WebCore/bindings/js/JSNamedNodeMapCustom.cpp +++ b/WebCore/bindings/js/JSNamedNodeMapCustom.cpp @@ -35,15 +35,47 @@ 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(propertyName); + return impl->getNamedItem(identifierToString(propertyName)); } -JSValue JSNamedNodeMap::nameGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) +JSValue JSNamedNodeMap::nameGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName) { - JSNamedNodeMap* thisObj = static_cast<JSNamedNodeMap*>(asObject(slot.slotBase())); - return toJS(exec, thisObj->impl()->getNamedItem(propertyName)); + JSNamedNodeMap* thisObj = static_cast<JSNamedNodeMap*>(asObject(slotBase)); + return toJS(exec, thisObj->impl()->getNamedItem(identifierToString(propertyName))); } void JSNamedNodeMap::markChildren(MarkStack& markStack) diff --git a/WebCore/bindings/js/JSNodeCustom.cpp b/WebCore/bindings/js/JSNodeCustom.cpp index 46a30a4..3a07b29 100644 --- a/WebCore/bindings/js/JSNodeCustom.cpp +++ b/WebCore/bindings/js/JSNodeCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2009, 2010 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -34,10 +34,12 @@ #include "DocumentType.h" #include "Entity.h" #include "EntityReference.h" +#include "ExceptionCode.h" #include "HTMLElement.h" #include "JSAttr.h" #include "JSCDATASection.h" #include "JSComment.h" +#include "JSDOMBinding.h" #include "JSDocument.h" #include "JSDocumentFragment.h" #include "JSDocumentType.h" @@ -66,12 +68,53 @@ using namespace JSC; namespace WebCore { -typedef int ExpectionCode; +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 = impl()->insertBefore(toNode(args.at(0)), toNode(args.at(1)), ec, true); + bool ok = imp->insertBefore(toNode(args.at(0)), toNode(args.at(1)), ec, true); setDOMException(exec, ec); if (ok) return args.at(0); @@ -80,8 +123,14 @@ 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 = impl()->replaceChild(toNode(args.at(0)), toNode(args.at(1)), ec, true); + bool ok = imp->replaceChild(toNode(args.at(0)), toNode(args.at(1)), ec, true); setDOMException(exec, ec); if (ok) return args.at(1); @@ -90,8 +139,14 @@ 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 = impl()->removeChild(toNode(args.at(0)), ec); + bool ok = imp->removeChild(toNode(args.at(0)), ec); setDOMException(exec, ec); if (ok) return args.at(0); @@ -100,8 +155,14 @@ 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 = impl()->appendChild(toNode(args.at(0)), ec, true); + bool ok = imp->appendChild(toNode(args.at(0)), ec, true); setDOMException(exec, ec); if (ok) return args.at(0); @@ -114,7 +175,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), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); + impl()->addEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); return jsUndefined(); } @@ -124,7 +185,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), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); + impl()->removeEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); return jsUndefined(); } @@ -162,6 +223,8 @@ void JSNode::markChildren(MarkStack& markStack) // case, the root of the detached subtree has a wrapper, so the tree will only // get marked once. Nodes that aren't outermost need to mark the outermost // in case it is otherwise unreachable. + // FIXME: In the non-common case of root not having a wrapper, this is still an O(n^2) algorithm, + // as we will traverse the whole tree as many times as there are nodes with wrappers in it. if (node != outermostNodeWithWrapper) { markDOMNodeWrapper(markStack, m_impl->document(), outermostNodeWithWrapper); return; @@ -172,7 +235,7 @@ void JSNode::markChildren(MarkStack& markStack) markDOMNodeWrapper(markStack, m_impl->document(), nodeToMark); } -static ALWAYS_INLINE JSValue createWrapper(ExecState* exec, JSDOMGlobalObject* globalObject, Node* node) +static ALWAYS_INLINE JSValue createWrapperInline(ExecState* exec, JSDOMGlobalObject* globalObject, Node* node) { ASSERT(node); ASSERT(!getCachedDOMNodeWrapper(exec, node->document(), node)); @@ -228,25 +291,18 @@ static ALWAYS_INLINE JSValue createWrapper(ExecState* exec, JSDOMGlobalObject* g return wrapper; } - -JSValue toJSNewlyCreated(ExecState* exec, JSDOMGlobalObject* globalObject, Node* node) + +JSValue createWrapper(ExecState* exec, JSDOMGlobalObject* globalObject, Node* node) { - if (!node) - return jsNull(); - - return createWrapper(exec, globalObject, node); + return createWrapperInline(exec, globalObject, node); } -JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, Node* node) +JSValue toJSNewlyCreated(ExecState* exec, JSDOMGlobalObject* globalObject, Node* node) { if (!node) return jsNull(); - - JSNode* wrapper = getCachedDOMNodeWrapper(exec, node->document(), node); - if (wrapper) - return wrapper; - - return createWrapper(exec, globalObject, node); + + return createWrapperInline(exec, globalObject, node); } } // namespace WebCore diff --git a/WebCore/bindings/js/JSNodeCustom.h b/WebCore/bindings/js/JSNodeCustom.h new file mode 100644 index 0000000..9d06ae6 --- /dev/null +++ b/WebCore/bindings/js/JSNodeCustom.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2007, 2009, 2010 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 JSNodeCustom_h +#define JSNodeCustom_h + +#include "JSDOMBinding.h" +#include <wtf/AlwaysInline.h> + +namespace WebCore { + +inline JSNode* getCachedDOMNodeWrapper(JSC::ExecState* exec, Document* document, Node* node) +{ + if (currentWorld(exec)->isNormal()) { + ASSERT(node->wrapper() == (document ? document->getWrapperCache(currentWorld(exec))->get(node) : domObjectWrapperMapFor(exec).get(node))); + return static_cast<JSNode*>(node->wrapper()); + } + + if (document) + return document->getWrapperCache(currentWorld(exec))->get(node); + return static_cast<JSNode*>(domObjectWrapperMapFor(exec).get(node)); +} + +JSC::JSValue createWrapper(JSC::ExecState*, JSDOMGlobalObject*, Node*); + +inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, Node* node) +{ + if (!node) + return JSC::jsNull(); + + JSNode* wrapper = getCachedDOMNodeWrapper(exec, node->document(), node); + if (wrapper) + return wrapper; + + return createWrapper(exec, globalObject, node); +} + +} + +#endif // JSDOMNodeCustom_h diff --git a/WebCore/bindings/js/JSNodeListCustom.cpp b/WebCore/bindings/js/JSNodeListCustom.cpp index 2821d01..d013e4f 100644 --- a/WebCore/bindings/js/JSNodeListCustom.cpp +++ b/WebCore/bindings/js/JSNodeListCustom.cpp @@ -53,13 +53,13 @@ CallType JSNodeList::getCallData(CallData& callData) bool JSNodeList::canGetItemsForName(ExecState*, NodeList* impl, const Identifier& propertyName) { - return impl->itemWithName(propertyName); + return impl->itemWithName(identifierToAtomicString(propertyName)); } -JSValue JSNodeList::nameGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) +JSValue JSNodeList::nameGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName) { - JSNodeList* thisObj = static_cast<JSNodeList*>(asObject(slot.slotBase())); - return toJS(exec, thisObj->impl()->itemWithName(propertyName)); + JSNodeList* thisObj = static_cast<JSNodeList*>(asObject(slotBase)); + return toJS(exec, thisObj->impl()->itemWithName(identifierToAtomicString(propertyName))); } } // namespace WebCore diff --git a/WebCore/bindings/js/JSOptionConstructor.cpp b/WebCore/bindings/js/JSOptionConstructor.cpp index 995903e..8b29136 100644 --- a/WebCore/bindings/js/JSOptionConstructor.cpp +++ b/WebCore/bindings/js/JSOptionConstructor.cpp @@ -51,11 +51,11 @@ static JSObject* constructHTMLOptionElement(ExecState* exec, JSObject* construct String data; if (!args.at(0).isUndefined()) - data = args.at(0).toString(exec); + data = ustringToString(args.at(0).toString(exec)); String value; if (!args.at(1).isUndefined()) - value = args.at(1).toString(exec); + value = ustringToString(args.at(1).toString(exec)); bool defaultSelected = args.at(2).toBoolean(exec); bool selected = args.at(3).toBoolean(exec); diff --git a/WebCore/bindings/js/JSPluginArrayCustom.cpp b/WebCore/bindings/js/JSPluginArrayCustom.cpp index 81d4295..b232f4d 100644 --- a/WebCore/bindings/js/JSPluginArrayCustom.cpp +++ b/WebCore/bindings/js/JSPluginArrayCustom.cpp @@ -30,13 +30,13 @@ using namespace JSC; bool JSPluginArray::canGetItemsForName(ExecState*, PluginArray* pluginArray, const Identifier& propertyName) { - return pluginArray->canGetItemsForName(propertyName); + return pluginArray->canGetItemsForName(identifierToAtomicString(propertyName)); } -JSValue JSPluginArray::nameGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) +JSValue JSPluginArray::nameGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName) { - JSPluginArray* thisObj = static_cast<JSPluginArray*>(asObject(slot.slotBase())); - return toJS(exec, thisObj->impl()->namedItem(propertyName)); + JSPluginArray* thisObj = static_cast<JSPluginArray*>(asObject(slotBase)); + return toJS(exec, thisObj->impl()->namedItem(identifierToAtomicString(propertyName))); } } // namespace WebCore diff --git a/WebCore/bindings/js/JSPluginCustom.cpp b/WebCore/bindings/js/JSPluginCustom.cpp index 555dd9e..9fa0b76 100644 --- a/WebCore/bindings/js/JSPluginCustom.cpp +++ b/WebCore/bindings/js/JSPluginCustom.cpp @@ -29,13 +29,13 @@ using namespace JSC; bool JSPlugin::canGetItemsForName(ExecState*, Plugin* plugin, const Identifier& propertyName) { - return plugin->canGetItemsForName(propertyName); + return plugin->canGetItemsForName(identifierToAtomicString(propertyName)); } -JSValue JSPlugin::nameGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) +JSValue JSPlugin::nameGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName) { - JSPlugin* thisObj = static_cast<JSPlugin*>(asObject(slot.slotBase())); - return toJS(exec, thisObj->impl()->namedItem(propertyName)); + JSPlugin* thisObj = static_cast<JSPlugin*>(asObject(slotBase)); + return toJS(exec, thisObj->impl()->namedItem(identifierToAtomicString(propertyName))); } } // namespace WebCore diff --git a/WebCore/bindings/js/JSPluginElementFunctions.cpp b/WebCore/bindings/js/JSPluginElementFunctions.cpp index e927ef1..b20b9a7 100644 --- a/WebCore/bindings/js/JSPluginElementFunctions.cpp +++ b/WebCore/bindings/js/JSPluginElementFunctions.cpp @@ -35,7 +35,7 @@ using namespace HTMLNames; // Runtime object support code for JSHTMLAppletElement, JSHTMLEmbedElement and JSHTMLObjectElement. -static Instance* pluginInstance(Node* node) +Instance* pluginInstance(Node* node) { if (!node) return 0; @@ -49,7 +49,7 @@ static Instance* pluginInstance(Node* node) return instance; } -static RuntimeObjectImp* getRuntimeObject(ExecState* exec, Node* node) +static RuntimeObject* getRuntimeObject(ExecState* exec, Node* node) { Instance* instance = pluginInstance(node); if (!instance) @@ -57,19 +57,11 @@ static RuntimeObjectImp* getRuntimeObject(ExecState* exec, Node* node) return instance->createRuntimeObject(exec); } -JSValue runtimeObjectGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue runtimeObjectPropertyGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName) { - JSHTMLElement* thisObj = static_cast<JSHTMLElement*>(asObject(slot.slotBase())); + JSHTMLElement* thisObj = static_cast<JSHTMLElement*>(asObject(slotBase)); HTMLElement* element = static_cast<HTMLElement*>(thisObj->impl()); - RuntimeObjectImp* runtimeObject = getRuntimeObject(exec, element); - return runtimeObject ? runtimeObject : jsUndefined(); -} - -JSValue runtimeObjectPropertyGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) -{ - JSHTMLElement* thisObj = static_cast<JSHTMLElement*>(asObject(slot.slotBase())); - HTMLElement* element = static_cast<HTMLElement*>(thisObj->impl()); - RuntimeObjectImp* runtimeObject = getRuntimeObject(exec, element); + RuntimeObject* runtimeObject = getRuntimeObject(exec, element); if (!runtimeObject) return jsUndefined(); return runtimeObject->get(exec, propertyName); @@ -77,7 +69,7 @@ JSValue runtimeObjectPropertyGetter(ExecState* exec, const Identifier& propertyN bool runtimeObjectCustomGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot, JSHTMLElement* element) { - RuntimeObjectImp* runtimeObject = getRuntimeObject(exec, element->impl()); + RuntimeObject* runtimeObject = getRuntimeObject(exec, element->impl()); if (!runtimeObject) return false; if (!runtimeObject->hasProperty(exec, propertyName)) @@ -88,7 +80,7 @@ bool runtimeObjectCustomGetOwnPropertySlot(ExecState* exec, const Identifier& pr bool runtimeObjectCustomGetOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, JSHTMLElement* element) { - RuntimeObjectImp* runtimeObject = getRuntimeObject(exec, element->impl()); + RuntimeObject* runtimeObject = getRuntimeObject(exec, element->impl()); if (!runtimeObject) return false; if (!runtimeObject->hasProperty(exec, propertyName)) @@ -104,7 +96,7 @@ bool runtimeObjectCustomGetOwnPropertyDescriptor(ExecState* exec, const Identifi bool runtimeObjectCustomPut(ExecState* exec, const Identifier& propertyName, JSValue value, HTMLElement* element, PutPropertySlot& slot) { - RuntimeObjectImp* runtimeObject = getRuntimeObject(exec, element); + RuntimeObject* runtimeObject = getRuntimeObject(exec, element); if (!runtimeObject) return 0; if (!runtimeObject->hasProperty(exec, propertyName)) diff --git a/WebCore/bindings/js/JSPluginElementFunctions.h b/WebCore/bindings/js/JSPluginElementFunctions.h index a5a323a..736ace9 100644 --- a/WebCore/bindings/js/JSPluginElementFunctions.h +++ b/WebCore/bindings/js/JSPluginElementFunctions.h @@ -22,6 +22,12 @@ #include "JSDOMBinding.h" +namespace JSC { +namespace Bindings { +class Instance; +} +} + namespace WebCore { class HTMLElement; @@ -29,9 +35,9 @@ namespace WebCore { class Node; // Runtime object support code for JSHTMLAppletElement, JSHTMLEmbedElement and JSHTMLObjectElement. + JSC::Bindings::Instance* pluginInstance(Node*); - JSC::JSValue runtimeObjectGetter(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&); - JSC::JSValue runtimeObjectPropertyGetter(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&); + JSC::JSValue runtimeObjectPropertyGetter(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&); bool runtimeObjectCustomGetOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&, JSHTMLElement*); bool runtimeObjectCustomGetOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&, JSHTMLElement*); bool runtimeObjectCustomPut(JSC::ExecState*, const JSC::Identifier&, JSC::JSValue, HTMLElement*, JSC::PutPropertySlot&); diff --git a/WebCore/bindings/js/JSPopStateEventCustom.cpp b/WebCore/bindings/js/JSPopStateEventCustom.cpp index 3f5fd7e..ce430ab 100644 --- a/WebCore/bindings/js/JSPopStateEventCustom.cpp +++ b/WebCore/bindings/js/JSPopStateEventCustom.cpp @@ -41,7 +41,7 @@ JSValue JSPopStateEvent::initPopStateEvent(ExecState* exec, const ArgList& args) RefPtr<SerializedScriptValue> stateObjectArg = SerializedScriptValue::create(exec, args.at(3)); PopStateEvent* event = static_cast<PopStateEvent*>(impl()); - event->initPopStateEvent(typeArg, canBubbleArg, cancelableArg, stateObjectArg.release()); + event->initPopStateEvent(ustringToAtomicString(typeArg), canBubbleArg, cancelableArg, stateObjectArg.release()); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSSQLResultSetRowListCustom.cpp b/WebCore/bindings/js/JSSQLResultSetRowListCustom.cpp index f40956e..0039a05 100644 --- a/WebCore/bindings/js/JSSQLResultSetRowListCustom.cpp +++ b/WebCore/bindings/js/JSSQLResultSetRowListCustom.cpp @@ -74,7 +74,7 @@ JSValue JSSQLResultSetRowList::item(ExecState* exec, const ArgList& args) ASSERT_NOT_REACHED(); } - object->putDirect(Identifier(exec, m_impl->columnNames()[i]), jsValue, DontDelete | ReadOnly); + object->putDirect(Identifier(exec, stringToUString(m_impl->columnNames()[i])), jsValue, DontDelete | ReadOnly); } return object; diff --git a/WebCore/bindings/js/JSSQLTransactionCustom.cpp b/WebCore/bindings/js/JSSQLTransactionCustom.cpp index e022401..81e6c63 100644 --- a/WebCore/bindings/js/JSSQLTransactionCustom.cpp +++ b/WebCore/bindings/js/JSSQLTransactionCustom.cpp @@ -49,7 +49,7 @@ JSValue JSSQLTransaction::executeSql(ExecState* exec, const ArgList& args) return jsUndefined(); } - String sqlStatement = args.at(0).toString(exec); + String sqlStatement = ustringToString(args.at(0).toString(exec)); if (exec->hadException()) return jsUndefined(); @@ -80,7 +80,7 @@ JSValue JSSQLTransaction::executeSql(ExecState* exec, const ArgList& args) sqlValues.append(value.uncheckedGetNumber()); else { // Convert the argument to a string and append it - sqlValues.append(value.toString(exec)); + sqlValues.append(ustringToString(value.toString(exec))); if (exec->hadException()) return jsUndefined(); } diff --git a/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp b/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp index b3bded5..fdcab06 100644 --- a/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp +++ b/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp @@ -52,7 +52,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), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); + impl()->addEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); return jsUndefined(); } @@ -62,7 +62,7 @@ JSValue JSSVGElementInstance::removeEventListener(ExecState* exec, const ArgList if (!listener.isObject()) return jsUndefined(); - impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); + impl()->removeEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSScriptProfileNodeCustom.cpp b/WebCore/bindings/js/JSScriptProfileNodeCustom.cpp new file mode 100644 index 0000000..127227e --- /dev/null +++ b/WebCore/bindings/js/JSScriptProfileNodeCustom.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * 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 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 "JSScriptProfileNode.h" + +#if ENABLE(JAVASCRIPT_DEBUGGER) +#include <profiler/ProfileNode.h> +#endif + +#include <runtime/JSArray.h> + +using namespace JSC; + +namespace WebCore { + +#if ENABLE(JAVASCRIPT_DEBUGGER) + +JSValue JSScriptProfileNode::callUID(ExecState* exec) const +{ + JSValue result = jsNumber(exec, impl()->callIdentifier().hash()); + return result; +} + +typedef Vector<RefPtr<ProfileNode> > ProfileNodesList; + +JSValue JSScriptProfileNode::children(ExecState* exec) const +{ + const ProfileNodesList& children = impl()->children(); + MarkedArgumentBuffer list; + + ProfileNodesList::const_iterator end = children.end(); + for (ProfileNodesList::const_iterator iter = children.begin(); iter != end; ++iter) + list.append(toJS(exec, iter->get())); + + return constructArray(exec, list); +} + +#endif + +} // namespace WebCore diff --git a/WebCore/bindings/js/JSSharedWorkerConstructor.cpp b/WebCore/bindings/js/JSSharedWorkerConstructor.cpp index c05b3d2..a66b1f7 100644 --- a/WebCore/bindings/js/JSSharedWorkerConstructor.cpp +++ b/WebCore/bindings/js/JSSharedWorkerConstructor.cpp @@ -71,7 +71,7 @@ static JSObject* constructSharedWorker(ExecState* exec, JSObject* constructor, c // FIXME: We need to use both the dynamic scope and the lexical scope (dynamic scope for resolving the worker URL) DOMWindow* window = asJSDOMWindow(exec->lexicalGlobalObject())->impl(); ExceptionCode ec = 0; - RefPtr<SharedWorker> worker = SharedWorker::create(scriptURL, name, window->document(), ec); + RefPtr<SharedWorker> worker = SharedWorker::create(ustringToString(scriptURL), ustringToString(name), window->document(), ec); setDOMException(exec, ec); return asObject(toJS(exec, jsConstructor->globalObject(), worker.release())); diff --git a/WebCore/bindings/js/JSStorageCustom.cpp b/WebCore/bindings/js/JSStorageCustom.cpp index 3cfe22e..6a126b7 100644 --- a/WebCore/bindings/js/JSStorageCustom.cpp +++ b/WebCore/bindings/js/JSStorageCustom.cpp @@ -38,13 +38,13 @@ namespace WebCore { bool JSStorage::canGetItemsForName(ExecState*, Storage* impl, const Identifier& propertyName) { - return impl->contains(propertyName); + return impl->contains(identifierToString(propertyName)); } -JSValue JSStorage::nameGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) +JSValue JSStorage::nameGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName) { - JSStorage* thisObj = static_cast<JSStorage*>(asObject(slot.slotBase())); - return jsStringOrNull(exec, thisObj->impl()->getItem(propertyName)); + JSStorage* thisObj = static_cast<JSStorage*>(asObject(slotBase)); + return jsStringOrNull(exec, thisObj->impl()->getItem(identifierToString(propertyName))); } bool JSStorage::deleteProperty(ExecState* exec, const Identifier& propertyName) @@ -60,7 +60,7 @@ bool JSStorage::deleteProperty(ExecState* exec, const Identifier& propertyName) if (prototype.isObject() && asObject(prototype)->hasProperty(exec, propertyName)) return false; - m_impl->removeItem(propertyName); + m_impl->removeItem(identifierToString(propertyName)); return true; } @@ -68,7 +68,7 @@ void JSStorage::getOwnPropertyNames(ExecState* exec, PropertyNameArray& property { unsigned length = m_impl->length(); for (unsigned i = 0; i < length; ++i) - propertyNames.add(Identifier(exec, m_impl->key(i))); + propertyNames.add(Identifier(exec, stringToUString(m_impl->key(i)))); Base::getOwnPropertyNames(exec, propertyNames, mode); } @@ -86,12 +86,12 @@ bool JSStorage::putDelegate(ExecState* exec, const Identifier& propertyName, JSV if (prototype.isObject() && asObject(prototype)->hasProperty(exec, propertyName)) return false; - String stringValue = value.toString(exec); + String stringValue = ustringToString(value.toString(exec)); if (exec->hadException()) return true; ExceptionCode ec = 0; - impl()->setItem(propertyName, stringValue, ec); + impl()->setItem(identifierToString(propertyName), stringValue, ec); setDOMException(exec, ec); return true; diff --git a/WebCore/bindings/js/JSStyleSheetListCustom.cpp b/WebCore/bindings/js/JSStyleSheetListCustom.cpp index 7bf9389..eb96a67 100644 --- a/WebCore/bindings/js/JSStyleSheetListCustom.cpp +++ b/WebCore/bindings/js/JSStyleSheetListCustom.cpp @@ -49,13 +49,13 @@ void JSStyleSheetList::markChildren(MarkStack& markStack) bool JSStyleSheetList::canGetItemsForName(ExecState*, StyleSheetList* styleSheetList, const Identifier& propertyName) { - return styleSheetList->getNamedItem(propertyName); + return styleSheetList->getNamedItem(identifierToString(propertyName)); } -JSValue JSStyleSheetList::nameGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) +JSValue JSStyleSheetList::nameGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName) { - JSStyleSheetList* thisObj = static_cast<JSStyleSheetList*>(asObject(slot.slotBase())); - HTMLStyleElement* element = thisObj->impl()->getNamedItem(propertyName); + JSStyleSheetList* thisObj = static_cast<JSStyleSheetList*>(asObject(slotBase)); + HTMLStyleElement* element = thisObj->impl()->getNamedItem(identifierToString(propertyName)); ASSERT(element); return toJS(exec, element->sheet()); } diff --git a/WebCore/bindings/js/JSWebGLArrayBufferConstructor.cpp b/WebCore/bindings/js/JSWebGLArrayBufferConstructor.cpp index 9742db7..8671908 100644 --- a/WebCore/bindings/js/JSWebGLArrayBufferConstructor.cpp +++ b/WebCore/bindings/js/JSWebGLArrayBufferConstructor.cpp @@ -30,7 +30,6 @@ #include "JSWebGLArrayBufferConstructor.h" #include "Document.h" -#include "WebGLArrayBuffer.h" #include "JSWebGLArrayBuffer.h" namespace WebCore { @@ -56,7 +55,12 @@ static JSObject* constructCanvasArrayBuffer(ExecState* exec, JSObject* construct if (isnan(size)) size = 0; } - return asObject(toJS(exec, jsConstructor->globalObject(), WebGLArrayBuffer::create(size))); + RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(size, 1); + if (!buffer.get()){ + setDOMException(exec, INDEX_SIZE_ERR); + return 0; + } + return asObject(toJS(exec, jsConstructor->globalObject(), buffer.get())); } JSC::ConstructType JSWebGLArrayBufferConstructor::getConstructData(JSC::ConstructData& constructData) diff --git a/WebCore/bindings/js/JSWebGLArrayBufferConstructor.h b/WebCore/bindings/js/JSWebGLArrayBufferConstructor.h index 98e364b..c7a927e 100644 --- a/WebCore/bindings/js/JSWebGLArrayBufferConstructor.h +++ b/WebCore/bindings/js/JSWebGLArrayBufferConstructor.h @@ -30,6 +30,7 @@ #include "JSDocument.h" #include "JSWebGLArrayBuffer.h" #include <runtime/Error.h> +#include "WebGLArrayBuffer.h" namespace WebCore { @@ -51,24 +52,30 @@ namespace WebCore { if (args.size() < 1) return C::create(0, 0, 0); + if (args.size() > 1 && !args.at(0).isObject()) + // Invalid first argument + return 0; + if (args.at(0).isObject()) { RefPtr<WebGLArrayBuffer> buffer = toWebGLArrayBuffer(args.at(0)); if (buffer) { - int offset = (args.size() > 1) ? args.at(1).toInt32(exec) : 0; - unsigned int length = (args.size() > 2) ? static_cast<unsigned int>(args.at(2).toInt32(exec)) : 0; + unsigned offset = (args.size() > 1) ? args.at(1).toUInt32(exec) : 0; + unsigned int length = (buffer->byteLength() - offset) / sizeof(T); + if (args.size() > 2) + length = args.at(2).toUInt32(exec); return C::create(buffer, offset, length); } JSC::JSObject* array = asObject(args.at(0)); - int length = array->get(exec, JSC::Identifier(exec, "length")).toInt32(exec); + unsigned length = array->get(exec, JSC::Identifier(exec, "length")).toUInt32(exec); void* tempValues; - if (!tryFastMalloc(length * sizeof(T)).getValue(tempValues)) { + if (!tryFastCalloc(length, sizeof(T)).getValue(tempValues)) { throwError(exec, JSC::GeneralError); return 0; } OwnFastMallocPtr<T> values(static_cast<T*>(tempValues)); - for (int i = 0; i < length; ++i) { + for (unsigned i = 0; i < length; ++i) { JSC::JSValue v = array->get(exec, i); if (exec->hadException()) return 0; @@ -78,7 +85,7 @@ namespace WebCore { return C::create(values.get(), length); } - unsigned size = static_cast<unsigned>(args.at(0).toInt32(exec)); + unsigned size = args.at(0).toUInt32(exec); return C::create(size); } diff --git a/WebCore/bindings/js/JSWebGLArrayCustom.cpp b/WebCore/bindings/js/JSWebGLArrayCustom.cpp index 9018544..d111d4e 100644 --- a/WebCore/bindings/js/JSWebGLArrayCustom.cpp +++ b/WebCore/bindings/js/JSWebGLArrayCustom.cpp @@ -67,6 +67,27 @@ JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, WebGLAr return jsUndefined(); } +JSValue JSWebGLArray::slice(ExecState* exec, const ArgList& args) +{ + WebGLArray* array = reinterpret_cast<WebGLArray*>(impl()); + + int start, end; + switch (args.size()) { + case 0: + start = 0; + end = array->length(); + break; + case 1: + start = args.at(0).toInt32(exec); + end = array->length(); + break; + default: + start = args.at(0).toInt32(exec); + end = args.at(1).toInt32(exec); + } + return toJS(exec, globalObject(), array->slice(start, end)); +} + } // namespace WebCore #endif // ENABLE(3D_CANVAS) diff --git a/WebCore/bindings/js/JSWebGLArrayHelper.h b/WebCore/bindings/js/JSWebGLArrayHelper.h index 3326d76..481c68f 100644 --- a/WebCore/bindings/js/JSWebGLArrayHelper.h +++ b/WebCore/bindings/js/JSWebGLArrayHelper.h @@ -43,14 +43,16 @@ JSC::JSValue setWebGLArrayFromArray(JSC::ExecState* exec, T* webGLArray, JSC::Ar if (args.at(0).isObject()) { // void set(in sequence<long> array, [Optional] in unsigned long offset); JSC::JSObject* array = JSC::asObject(args.at(0)); - unsigned offset = 0; + uint32_t offset = 0; if (args.size() == 2) offset = args.at(1).toInt32(exec); - int length = array->get(exec, JSC::Identifier(exec, "length")).toInt32(exec); - if (offset + length > webGLArray->length()) + uint32_t length = array->get(exec, JSC::Identifier(exec, "length")).toInt32(exec); + if (offset > webGLArray->length() || + offset + length > webGLArray->length() || + offset + length < offset) setDOMException(exec, INDEX_SIZE_ERR); else { - for (int i = 0; i < length; i++) { + for (uint32_t i = 0; i < length; i++) { JSC::JSValue v = array->get(exec, i); if (exec->hadException()) return JSC::jsUndefined(); diff --git a/WebCore/bindings/js/JSWebGLByteArrayConstructor.cpp b/WebCore/bindings/js/JSWebGLByteArrayConstructor.cpp index 7db710f..f76fb1d 100644 --- a/WebCore/bindings/js/JSWebGLByteArrayConstructor.cpp +++ b/WebCore/bindings/js/JSWebGLByteArrayConstructor.cpp @@ -53,6 +53,10 @@ static JSObject* constructCanvasByteArray(ExecState* exec, JSObject* constructor { JSWebGLByteArrayConstructor* jsConstructor = static_cast<JSWebGLByteArrayConstructor*>(constructor); RefPtr<WebGLByteArray> array = static_cast<WebGLByteArray*>(construct<WebGLByteArray, signed char>(exec, args).get()); + if (!array.get()) { + setDOMException(exec, INDEX_SIZE_ERR); + return 0; + } return asObject(toJS(exec, jsConstructor->globalObject(), array.get())); } diff --git a/WebCore/bindings/js/JSWebGLFloatArrayConstructor.cpp b/WebCore/bindings/js/JSWebGLFloatArrayConstructor.cpp index 707fe56..e6375ac 100644 --- a/WebCore/bindings/js/JSWebGLFloatArrayConstructor.cpp +++ b/WebCore/bindings/js/JSWebGLFloatArrayConstructor.cpp @@ -53,6 +53,10 @@ static JSObject* constructCanvasFloatArray(ExecState* exec, JSObject* constructo { JSWebGLFloatArrayConstructor* jsConstructor = static_cast<JSWebGLFloatArrayConstructor*>(constructor); RefPtr<WebGLFloatArray> array = static_cast<WebGLFloatArray*>(construct<WebGLFloatArray, float>(exec, args).get()); + if (!array.get()) { + setDOMException(exec, INDEX_SIZE_ERR); + return 0; + } return asObject(toJS(exec, jsConstructor->globalObject(), array.get())); } diff --git a/WebCore/bindings/js/JSWebGLIntArrayConstructor.cpp b/WebCore/bindings/js/JSWebGLIntArrayConstructor.cpp index f2a0922..5b14803 100644 --- a/WebCore/bindings/js/JSWebGLIntArrayConstructor.cpp +++ b/WebCore/bindings/js/JSWebGLIntArrayConstructor.cpp @@ -53,6 +53,10 @@ static JSObject* constructCanvasIntArray(ExecState* exec, JSObject* constructor, { JSWebGLIntArrayConstructor* jsConstructor = static_cast<JSWebGLIntArrayConstructor*>(constructor); RefPtr<WebGLIntArray> array = static_cast<WebGLIntArray*>(construct<WebGLIntArray, int>(exec, args).get()); + if (!array.get()) { + setDOMException(exec, INDEX_SIZE_ERR); + return 0; + } return asObject(toJS(exec, jsConstructor->globalObject(), array.get())); } diff --git a/WebCore/bindings/js/JSWebGLShortArrayConstructor.cpp b/WebCore/bindings/js/JSWebGLShortArrayConstructor.cpp index 74bfe5c..a33779b 100644 --- a/WebCore/bindings/js/JSWebGLShortArrayConstructor.cpp +++ b/WebCore/bindings/js/JSWebGLShortArrayConstructor.cpp @@ -54,6 +54,10 @@ static JSObject* constructCanvasShortArray(ExecState* exec, JSObject* constructo { JSWebGLShortArrayConstructor* jsConstructor = static_cast<JSWebGLShortArrayConstructor*>(constructor); RefPtr<WebGLShortArray> array = static_cast<WebGLShortArray*>(construct<WebGLShortArray, short>(exec, args).get()); + if (!array.get()) { + setDOMException(exec, INDEX_SIZE_ERR); + return 0; + } return asObject(toJS(exec, jsConstructor->globalObject(), array.get())); } diff --git a/WebCore/bindings/js/JSWebGLUnsignedByteArrayConstructor.cpp b/WebCore/bindings/js/JSWebGLUnsignedByteArrayConstructor.cpp index d5597ce..dcb940e 100644 --- a/WebCore/bindings/js/JSWebGLUnsignedByteArrayConstructor.cpp +++ b/WebCore/bindings/js/JSWebGLUnsignedByteArrayConstructor.cpp @@ -30,6 +30,7 @@ #include "JSWebGLUnsignedByteArrayConstructor.h" #include "Document.h" +#include "ExceptionCode.h" #include "WebGLUnsignedByteArray.h" #include "JSWebGLArrayBuffer.h" #include "JSWebGLArrayBufferConstructor.h" @@ -53,6 +54,10 @@ static JSObject* constructCanvasUnsignedByteArray(ExecState* exec, JSObject* con { JSWebGLUnsignedByteArrayConstructor* jsConstructor = static_cast<JSWebGLUnsignedByteArrayConstructor*>(constructor); RefPtr<WebGLUnsignedByteArray> array = static_cast<WebGLUnsignedByteArray*>(construct<WebGLUnsignedByteArray, unsigned char>(exec, args).get()); + if (!array.get()) { + setDOMException(exec, INDEX_SIZE_ERR); + return 0; + } return asObject(toJS(exec, jsConstructor->globalObject(), array.get())); } diff --git a/WebCore/bindings/js/JSWebGLUnsignedIntArrayConstructor.cpp b/WebCore/bindings/js/JSWebGLUnsignedIntArrayConstructor.cpp index 6fafa81..23fccce 100644 --- a/WebCore/bindings/js/JSWebGLUnsignedIntArrayConstructor.cpp +++ b/WebCore/bindings/js/JSWebGLUnsignedIntArrayConstructor.cpp @@ -53,6 +53,10 @@ static JSObject* constructCanvasUnsignedIntArray(ExecState* exec, JSObject* cons { JSWebGLUnsignedIntArrayConstructor* jsConstructor = static_cast<JSWebGLUnsignedIntArrayConstructor*>(constructor); RefPtr<WebGLUnsignedIntArray> array = static_cast<WebGLUnsignedIntArray*>(construct<WebGLUnsignedIntArray, unsigned int>(exec, args).get()); + if (!array.get()) { + setDOMException(exec, INDEX_SIZE_ERR); + return 0; + } return asObject(toJS(exec, jsConstructor->globalObject(), array.get())); } diff --git a/WebCore/bindings/js/JSWebGLUnsignedShortArrayConstructor.cpp b/WebCore/bindings/js/JSWebGLUnsignedShortArrayConstructor.cpp index deaeffd..d8c2cfb 100644 --- a/WebCore/bindings/js/JSWebGLUnsignedShortArrayConstructor.cpp +++ b/WebCore/bindings/js/JSWebGLUnsignedShortArrayConstructor.cpp @@ -53,6 +53,10 @@ static JSObject* constructCanvasUnsignedShortArray(ExecState* exec, JSObject* co { JSWebGLUnsignedShortArrayConstructor* jsConstructor = static_cast<JSWebGLUnsignedShortArrayConstructor*>(constructor); RefPtr<WebGLUnsignedShortArray> array = static_cast<WebGLUnsignedShortArray*>(construct<WebGLUnsignedShortArray, unsigned short>(exec, args).get()); + if (!array.get()) { + setDOMException(exec, INDEX_SIZE_ERR); + return 0; + } return asObject(toJS(exec, jsConstructor->globalObject(), array.get())); } diff --git a/WebCore/bindings/js/JSWebKitCSSMatrixConstructor.cpp b/WebCore/bindings/js/JSWebKitCSSMatrixConstructor.cpp index bc05250..baf174e 100644 --- a/WebCore/bindings/js/JSWebKitCSSMatrixConstructor.cpp +++ b/WebCore/bindings/js/JSWebKitCSSMatrixConstructor.cpp @@ -47,7 +47,7 @@ static JSObject* constructWebKitCSSMatrix(ExecState* exec, JSObject* constructor JSWebKitCSSMatrixConstructor* jsConstructor = static_cast<JSWebKitCSSMatrixConstructor*>(constructor); String s; if (args.size() >= 1) - s = args.at(0).toString(exec); + s = ustringToString(args.at(0).toString(exec)); ExceptionCode ec = 0; RefPtr<WebKitCSSMatrix> matrix = WebKitCSSMatrix::create(s, ec); diff --git a/WebCore/bindings/js/JSWebSocketConstructor.cpp b/WebCore/bindings/js/JSWebSocketConstructor.cpp index 5b34765..57b7477 100644 --- a/WebCore/bindings/js/JSWebSocketConstructor.cpp +++ b/WebCore/bindings/js/JSWebSocketConstructor.cpp @@ -64,7 +64,7 @@ static JSObject* constructWebSocket(ExecState* exec, JSObject* constructor, cons if (args.size() == 0) return throwError(exec, SyntaxError, "Not enough arguments"); - const String& urlString = args.at(0).toString(exec); + const String& urlString = ustringToString(args.at(0).toString(exec)); if (exec->hadException()) return throwError(exec, SyntaxError, "wrong URL"); const KURL& url = context->completeURL(urlString); @@ -73,7 +73,7 @@ static JSObject* constructWebSocket(ExecState* exec, JSObject* constructor, cons if (args.size() < 2) webSocket->connect(url, ec); else { - const String& protocol = args.at(1).toString(exec); + const String& protocol = ustringToString(args.at(1).toString(exec)); if (exec->hadException()) return 0; webSocket->connect(url, protocol, ec); diff --git a/WebCore/bindings/js/JSWebSocketCustom.cpp b/WebCore/bindings/js/JSWebSocketCustom.cpp index d610f01..18f4183 100644 --- a/WebCore/bindings/js/JSWebSocketCustom.cpp +++ b/WebCore/bindings/js/JSWebSocketCustom.cpp @@ -50,7 +50,7 @@ JSValue JSWebSocket::send(ExecState* exec, const ArgList& args) if (args.size() < 1) return throwError(exec, SyntaxError, "Not enough arguments"); - const String& msg = args.at(0).toString(exec); + const String& msg = ustringToString(args.at(0).toString(exec)); if (exec->hadException()) return throwError(exec, SyntaxError, "bad message data."); ExceptionCode ec = 0; @@ -65,7 +65,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), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); + impl()->addEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); return jsUndefined(); } @@ -75,7 +75,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), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); + impl()->removeEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSWorkerConstructor.cpp b/WebCore/bindings/js/JSWorkerConstructor.cpp index 69c05e7..43c685e 100644 --- a/WebCore/bindings/js/JSWorkerConstructor.cpp +++ b/WebCore/bindings/js/JSWorkerConstructor.cpp @@ -64,7 +64,7 @@ static JSObject* constructWorker(ExecState* exec, JSObject* constructor, const A DOMWindow* window = asJSDOMWindow(exec->lexicalGlobalObject())->impl(); ExceptionCode ec = 0; - RefPtr<Worker> worker = Worker::create(scriptURL, window->document(), ec); + RefPtr<Worker> worker = Worker::create(ustringToString(scriptURL), window->document(), ec); if (ec) { setDOMException(exec, ec); return 0; diff --git a/WebCore/bindings/js/JSWorkerContextCustom.cpp b/WebCore/bindings/js/JSWorkerContextCustom.cpp index bf9409c..0a9489b 100644 --- a/WebCore/bindings/js/JSWorkerContextCustom.cpp +++ b/WebCore/bindings/js/JSWorkerContextCustom.cpp @@ -105,18 +105,13 @@ JSValue JSWorkerContext::importScripts(ExecState* exec, const ArgList& args) Vector<String> urls; for (unsigned i = 0; i < args.size(); i++) { - urls.append(args.at(i).toString(exec)); + urls.append(ustringToString(args.at(i).toString(exec))); if (exec->hadException()) return jsUndefined(); } ExceptionCode ec = 0; - int signedLineNumber; - intptr_t sourceID; - UString sourceURL; - JSValue function; - exec->interpreter()->retrieveLastCaller(exec, signedLineNumber, sourceID, sourceURL, function); - impl()->importScripts(urls, sourceURL, signedLineNumber >= 0 ? signedLineNumber : 0, ec); + impl()->importScripts(urls, ec); setDOMException(exec, ec); return jsUndefined(); } @@ -127,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), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); + impl()->addEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); return jsUndefined(); } @@ -137,7 +132,7 @@ JSValue JSWorkerContext::removeEventListener(ExecState* exec, const ArgList& arg if (!listener.isObject()) return jsUndefined(); - impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); + impl()->removeEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSWorkerContextErrorHandler.cpp b/WebCore/bindings/js/JSWorkerContextErrorHandler.cpp new file mode 100644 index 0000000..ad3f5ec --- /dev/null +++ b/WebCore/bindings/js/JSWorkerContextErrorHandler.cpp @@ -0,0 +1,116 @@ +/* + * 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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" + +#if ENABLE(WORKERS) + +#include "JSWorkerContextErrorHandler.h" + +#include "ErrorEvent.h" +#include "Event.h" +#include "JSEvent.h" +#include <runtime/JSLock.h> + +using namespace JSC; + +namespace WebCore { + +JSWorkerContextErrorHandler::JSWorkerContextErrorHandler(JSObject* function, JSObject* wrapper, bool isAttribute, DOMWrapperWorld* isolatedWorld) + : JSEventListener(function, wrapper, isAttribute, isolatedWorld) +{ +} + +JSWorkerContextErrorHandler::~JSWorkerContextErrorHandler() +{ +} + +void JSWorkerContextErrorHandler::handleEvent(ScriptExecutionContext* scriptExecutionContext, Event* event) +{ + ASSERT(scriptExecutionContext); + if (!scriptExecutionContext) + return; + + JSLock lock(SilenceAssertionsOnly); + + JSObject* jsFunction = this->jsFunction(scriptExecutionContext); + if (!jsFunction) + return; + + JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(scriptExecutionContext, isolatedWorld()); + if (!globalObject) + return; + + ExecState* exec = globalObject->globalExec(); + + CallData callData; + CallType callType = jsFunction->getCallData(callData); + + if (callType != CallTypeNone) { + + ref(); + + Event* savedEvent = globalObject->currentEvent(); + globalObject->setCurrentEvent(event); + + ASSERT(event->isErrorEvent()); + ErrorEvent* errorEvent = static_cast<ErrorEvent*>(event); + + MarkedArgumentBuffer args; + args.append(jsString(exec, errorEvent->message())); + args.append(jsString(exec, errorEvent->filename())); + args.append(jsNumber(exec, errorEvent->lineno())); + + JSGlobalData* globalData = globalObject->globalData(); + DynamicGlobalObjectScope globalObjectScope(exec, globalData->dynamicGlobalObject ? globalData->dynamicGlobalObject : globalObject); + + JSValue thisValue = globalObject->toThisObject(exec); + + globalData->timeoutChecker.start(); + JSValue returnValue = JSC::call(exec, jsFunction, callType, callData, thisValue, args); + globalData->timeoutChecker.stop(); + + globalObject->setCurrentEvent(savedEvent); + + if (exec->hadException()) + reportCurrentException(exec); + else { + bool retvalbool; + if (returnValue.getBoolean(retvalbool) && !retvalbool) + event->preventDefault(); + } + + deref(); + } +} + +} // namespace WebCore + +#endif // ENABLE(WORKERS) diff --git a/WebCore/bindings/js/JSWorkerContextErrorHandler.h b/WebCore/bindings/js/JSWorkerContextErrorHandler.h new file mode 100644 index 0000000..a188299 --- /dev/null +++ b/WebCore/bindings/js/JSWorkerContextErrorHandler.h @@ -0,0 +1,64 @@ +/* + * 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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 JSWorkerContextErrorHandler_h +#define JSWorkerContextErrorHandler_h + +#include "JSEventListener.h" + +namespace WebCore { + +class JSWorkerContextErrorHandler : public JSEventListener { +public: + static PassRefPtr<JSWorkerContextErrorHandler> create(JSC::JSObject* listener, JSC::JSObject* wrapper, bool isAttribute, DOMWrapperWorld* isolatedWorld) + { + return adoptRef(new JSWorkerContextErrorHandler(listener, wrapper, isAttribute, isolatedWorld)); + } + + virtual ~JSWorkerContextErrorHandler(); + +private: + JSWorkerContextErrorHandler(JSC::JSObject* function, JSC::JSObject* wrapper, bool isAttribute, DOMWrapperWorld* isolatedWorld); + virtual void handleEvent(ScriptExecutionContext*, Event*); +}; + +// Creates a JS EventListener for "onerror" event handler in worker context. It has custom implementation because +// unlike other event listeners it accepts three parameters. +inline PassRefPtr<JSWorkerContextErrorHandler> createJSWorkerContextErrorHandler(JSC::ExecState* exec, JSC::JSValue listener, JSC::JSObject* wrapper) +{ + if (!listener.isObject()) + return 0; + + return JSWorkerContextErrorHandler::create(asObject(listener), wrapper, true, currentWorld(exec)); +} + +} // namespace WebCore + +#endif // JSWorkerContextErrorHandler_h diff --git a/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp b/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp index e20b6d9..da83801 100644 --- a/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp +++ b/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp @@ -30,6 +30,7 @@ #include "JSXMLHttpRequest.h" #include "Blob.h" +#include "DOMFormData.h" #include "DOMWindow.h" #include "Document.h" #include "Event.h" @@ -37,6 +38,7 @@ #include "FrameLoader.h" #include "HTMLDocument.h" #include "JSBlob.h" +#include "JSDOMFormData.h" #include "JSDOMWindowCustom.h" #include "JSDocument.h" #include "JSEvent.h" @@ -65,23 +67,25 @@ JSValue JSXMLHttpRequest::open(ExecState* exec, const ArgList& args) if (args.size() < 2) return throwError(exec, SyntaxError, "Not enough arguments"); - const KURL& url = impl()->scriptExecutionContext()->completeURL(args.at(1).toString(exec)); - String method = args.at(0).toString(exec); - bool async = true; - if (args.size() >= 3) - async = args.at(2).toBoolean(exec); + const KURL& url = impl()->scriptExecutionContext()->completeURL(ustringToString(args.at(1).toString(exec))); + String method = ustringToString(args.at(0).toString(exec)); ExceptionCode ec = 0; - if (args.size() >= 4 && !args.at(3).isUndefined()) { - String user = valueToStringWithNullCheck(exec, args.at(3)); - - if (args.size() >= 5 && !args.at(4).isUndefined()) { - String password = valueToStringWithNullCheck(exec, args.at(4)); - impl()->open(method, url, async, user, password, ec); + if (args.size() >= 3) { + bool async = args.at(2).toBoolean(exec); + + if (args.size() >= 4 && !args.at(3).isUndefined()) { + String user = valueToStringWithNullCheck(exec, args.at(3)); + + if (args.size() >= 5 && !args.at(4).isUndefined()) { + String password = valueToStringWithNullCheck(exec, args.at(4)); + impl()->open(method, url, async, user, password, ec); + } else + impl()->open(method, url, async, user, ec); } else - impl()->open(method, url, async, user, ec); + impl()->open(method, url, async, ec); } else - impl()->open(method, url, async, ec); + impl()->open(method, url, ec); setDOMException(exec, ec); return jsUndefined(); @@ -93,7 +97,7 @@ JSValue JSXMLHttpRequest::setRequestHeader(ExecState* exec, const ArgList& args) return throwError(exec, SyntaxError, "Not enough arguments"); ExceptionCode ec = 0; - impl()->setRequestHeader(args.at(0).toString(exec), args.at(1).toString(exec), ec); + impl()->setRequestHeader(ustringToAtomicString(args.at(0).toString(exec)), ustringToString(args.at(1).toString(exec)), ec); setDOMException(exec, ec); return jsUndefined(); } @@ -111,8 +115,10 @@ JSValue JSXMLHttpRequest::send(ExecState* exec, const ArgList& args) impl()->send(toDocument(val), ec); else if (val.inherits(&JSBlob::s_info)) impl()->send(toBlob(val), ec); + else if (val.inherits(&JSDOMFormData::s_info)) + impl()->send(toDOMFormData(val), ec); else - impl()->send(val.toString(exec), ec); + impl()->send(ustringToString(val.toString(exec)), ec); } int signedLineNumber; @@ -121,7 +127,7 @@ JSValue JSXMLHttpRequest::send(ExecState* exec, const ArgList& args) JSValue function; exec->interpreter()->retrieveLastCaller(exec, signedLineNumber, sourceID, sourceURL, function); impl()->setLastSendLineNumber(signedLineNumber >= 0 ? signedLineNumber : 0); - impl()->setLastSendURL(sourceURL); + impl()->setLastSendURL(ustringToString(sourceURL)); setDOMException(exec, ec); return jsUndefined(); @@ -133,7 +139,7 @@ JSValue JSXMLHttpRequest::getResponseHeader(ExecState* exec, const ArgList& args return throwError(exec, SyntaxError, "Not enough arguments"); ExceptionCode ec = 0; - JSValue header = jsStringOrNull(exec, impl()->getResponseHeader(args.at(0).toString(exec), ec)); + JSValue header = jsStringOrNull(exec, impl()->getResponseHeader(ustringToAtomicString(args.at(0).toString(exec)), ec)); setDOMException(exec, ec); return header; } @@ -143,7 +149,7 @@ JSValue JSXMLHttpRequest::overrideMimeType(ExecState* exec, const ArgList& args) if (args.size() < 1) return throwError(exec, SyntaxError, "Not enough arguments"); - impl()->overrideMimeType(args.at(0).toString(exec)); + impl()->overrideMimeType(ustringToString(args.at(0).toString(exec))); return jsUndefined(); } @@ -153,7 +159,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), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); + impl()->addEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); return jsUndefined(); } @@ -163,7 +169,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), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); + impl()->removeEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSXMLHttpRequestUploadCustom.cpp b/WebCore/bindings/js/JSXMLHttpRequestUploadCustom.cpp index 857c12d..42d4eb9 100644 --- a/WebCore/bindings/js/JSXMLHttpRequestUploadCustom.cpp +++ b/WebCore/bindings/js/JSXMLHttpRequestUploadCustom.cpp @@ -57,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), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); + impl()->addEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); return jsUndefined(); } @@ -67,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), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); + impl()->removeEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSXSLTProcessorCustom.cpp b/WebCore/bindings/js/JSXSLTProcessorCustom.cpp index 441bbc9..49ac234 100644 --- a/WebCore/bindings/js/JSXSLTProcessorCustom.cpp +++ b/WebCore/bindings/js/JSXSLTProcessorCustom.cpp @@ -89,9 +89,9 @@ JSValue JSXSLTProcessor::setParameter(ExecState* exec, const ArgList& args) { if (args.at(1).isUndefinedOrNull() || args.at(2).isUndefinedOrNull()) return jsUndefined(); // Throw exception? - String namespaceURI = args.at(0).toString(exec); - String localName = args.at(1).toString(exec); - String value = args.at(2).toString(exec); + String namespaceURI = ustringToString(args.at(0).toString(exec)); + String localName = ustringToString(args.at(1).toString(exec)); + String value = ustringToString(args.at(2).toString(exec)); impl()->setParameter(namespaceURI, localName, value); return jsUndefined(); } @@ -100,8 +100,8 @@ JSValue JSXSLTProcessor::getParameter(ExecState* exec, const ArgList& args) { if (args.at(1).isUndefinedOrNull()) return jsUndefined(); - String namespaceURI = args.at(0).toString(exec); - String localName = args.at(1).toString(exec); + String namespaceURI = ustringToString(args.at(0).toString(exec)); + String localName = ustringToString(args.at(1).toString(exec)); String value = impl()->getParameter(namespaceURI, localName); return jsStringOrUndefined(exec, value); } @@ -110,8 +110,8 @@ JSValue JSXSLTProcessor::removeParameter(ExecState* exec, const ArgList& args) { if (args.at(1).isUndefinedOrNull()) return jsUndefined(); - String namespaceURI = args.at(0).toString(exec); - String localName = args.at(1).toString(exec); + String namespaceURI = ustringToString(args.at(0).toString(exec)); + String localName = ustringToString(args.at(1).toString(exec)); impl()->removeParameter(namespaceURI, localName); return jsUndefined(); } diff --git a/WebCore/bindings/js/JavaScriptCallFrame.cpp b/WebCore/bindings/js/JavaScriptCallFrame.cpp new file mode 100644 index 0000000..c280d98 --- /dev/null +++ b/WebCore/bindings/js/JavaScriptCallFrame.cpp @@ -0,0 +1,115 @@ +/* + * 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 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 "JavaScriptCallFrame.h" + +#include "JSDOMBinding.h" + +#if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC) + +#include "PlatformString.h" +#include <debugger/DebuggerCallFrame.h> +#include <runtime/Completion.h> +#include <runtime/JSGlobalObject.h> +#include <runtime/JSLock.h> +#include <runtime/JSObject.h> +#include <runtime/JSValue.h> + +using namespace JSC; + +namespace WebCore { + +JavaScriptCallFrame::JavaScriptCallFrame(const DebuggerCallFrame& debuggerCallFrame, PassRefPtr<JavaScriptCallFrame> caller, intptr_t sourceID, int line) + : m_debuggerCallFrame(debuggerCallFrame) + , m_caller(caller) + , m_sourceID(sourceID) + , m_line(line) + , m_isValid(true) +{ +} + +JavaScriptCallFrame* JavaScriptCallFrame::caller() +{ + return m_caller.get(); +} + +const JSC::ScopeChainNode* JavaScriptCallFrame::scopeChain() const +{ + ASSERT(m_isValid); + if (!m_isValid) + return 0; + return m_debuggerCallFrame.scopeChain(); +} + +JSC::JSGlobalObject* JavaScriptCallFrame::dynamicGlobalObject() const +{ + ASSERT(m_isValid); + if (!m_isValid) + return 0; + return m_debuggerCallFrame.dynamicGlobalObject(); +} + +String JavaScriptCallFrame::functionName() const +{ + ASSERT(m_isValid); + if (!m_isValid) + return String(); + UString functionName = m_debuggerCallFrame.calculatedFunctionName(); + if (functionName.isEmpty()) + return String(); + return ustringToString(functionName); +} + +DebuggerCallFrame::Type JavaScriptCallFrame::type() const +{ + ASSERT(m_isValid); + if (!m_isValid) + return DebuggerCallFrame::ProgramType; + return m_debuggerCallFrame.type(); +} + +JSObject* JavaScriptCallFrame::thisObject() const +{ + ASSERT(m_isValid); + if (!m_isValid) + return 0; + return m_debuggerCallFrame.thisObject(); +} + +// Evaluate some JavaScript code in the scope of this frame. +JSValue JavaScriptCallFrame::evaluate(const UString& script, JSValue& exception) const +{ + ASSERT(m_isValid); + if (!m_isValid) + return jsNull(); + + JSLock lock(SilenceAssertionsOnly); + return m_debuggerCallFrame.evaluate(script, exception); +} + +} // namespace WebCore + +#endif // ENABLE(JAVASCRIPT_DEBUGGER) diff --git a/WebCore/bindings/js/JavaScriptCallFrame.h b/WebCore/bindings/js/JavaScriptCallFrame.h new file mode 100644 index 0000000..574c782 --- /dev/null +++ b/WebCore/bindings/js/JavaScriptCallFrame.h @@ -0,0 +1,89 @@ +/* + * 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 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. + */ + +#ifndef JavaScriptCallFrame_h +#define JavaScriptCallFrame_h + +#if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC) + +#include <debugger/DebuggerCallFrame.h> +#include <interpreter/CallFrame.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> + +namespace WebCore { + +class String; + +class JavaScriptCallFrame : public RefCounted<JavaScriptCallFrame> { +public: + static PassRefPtr<JavaScriptCallFrame> create(const JSC::DebuggerCallFrame& debuggerCallFrame, PassRefPtr<JavaScriptCallFrame> caller, intptr_t sourceID, int line) + { + return adoptRef(new JavaScriptCallFrame(debuggerCallFrame, caller, sourceID, line)); + } + + void invalidate() + { + m_isValid = false; + m_debuggerCallFrame = 0; + } + + bool isValid() const { return m_isValid; } + + JavaScriptCallFrame* caller(); + + intptr_t sourceID() const { return m_sourceID; } + int line() const { return m_line; } + void update(const JSC::DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int line) + { + m_debuggerCallFrame = debuggerCallFrame; + m_line = line; + m_sourceID = sourceID; + m_isValid = true; + } + + String functionName() const; + JSC::DebuggerCallFrame::Type type() const; + const JSC::ScopeChainNode* scopeChain() const; + JSC::JSGlobalObject* dynamicGlobalObject() const; + + JSC::JSObject* thisObject() const; + JSC::JSValue evaluate(const JSC::UString& script, JSC::JSValue& exception) const; + +private: + JavaScriptCallFrame(const JSC::DebuggerCallFrame&, PassRefPtr<JavaScriptCallFrame> caller, intptr_t sourceID, int line); + + JSC::DebuggerCallFrame m_debuggerCallFrame; + RefPtr<JavaScriptCallFrame> m_caller; + intptr_t m_sourceID; + int m_line; + bool m_isValid; +}; + +} // namespace WebCore + +#endif // ENABLE(JAVASCRIPT_DEBUGGER) + +#endif // JavaScriptCallFrame_h diff --git a/WebCore/bindings/js/JavaScriptProfile.cpp b/WebCore/bindings/js/JavaScriptProfile.cpp deleted file mode 100644 index 8e56ed8..0000000 --- a/WebCore/bindings/js/JavaScriptProfile.cpp +++ /dev/null @@ -1,183 +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 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 "JavaScriptProfile.h" - -#if ENABLE(JAVASCRIPT_DEBUGGER) - -#include "JavaScriptProfileNode.h" -#include <JavaScriptCore/APICast.h> -#include <JavaScriptCore/JSObjectRef.h> -#include <JavaScriptCore/JSStringRef.h> -#include <JavaScriptCore/OpaqueJSString.h> -#include <profiler/Profile.h> -#include <runtime/JSObject.h> -#include <runtime/JSValue.h> -#include <wtf/StdLibExtras.h> - -using namespace JSC; - -namespace WebCore { - -// Cache - -typedef HashMap<Profile*, JSObject*> ProfileMap; - -static ProfileMap& profileCache() -{ - DEFINE_STATIC_LOCAL(ProfileMap, staticProfiles, ()); - return staticProfiles; -} - -// Static Values - -static JSClassRef ProfileClass(); - -static JSValueRef getTitleCallback(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*) -{ - if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileClass())) - return JSValueMakeUndefined(ctx); - - Profile* profile = static_cast<Profile*>(JSObjectGetPrivate(thisObject)); - return JSValueMakeString(ctx, OpaqueJSString::create(profile->title()).get()); -} - -static JSValueRef getHeadCallback(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*) -{ - if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileClass())) - return JSValueMakeUndefined(ctx); - - ExecState* exec = toJS(ctx); - Profile* profile = static_cast<Profile*>(JSObjectGetPrivate(thisObject)); - return toRef(exec, toJS(exec, profile->head())); -} - -static JSValueRef getUniqueIdCallback(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*) -{ - if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileClass())) - return JSValueMakeUndefined(ctx); - - Profile* profile = static_cast<Profile*>(JSObjectGetPrivate(thisObject)); - return JSValueMakeNumber(ctx, profile->uid()); -} - -// Static Functions - -static JSValueRef focus(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* /*exception*/) -{ - if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileClass())) - return JSValueMakeUndefined(ctx); - - if (argumentCount < 1) - return JSValueMakeUndefined(ctx); - - if (!JSValueIsObjectOfClass(ctx, arguments[0], ProfileNodeClass())) - return JSValueMakeUndefined(ctx); - - Profile* profile = static_cast<Profile*>(JSObjectGetPrivate(thisObject)); - profile->focus(static_cast<ProfileNode*>(JSObjectGetPrivate(const_cast<JSObjectRef>(arguments[0])))); - - return JSValueMakeUndefined(ctx); -} - -static JSValueRef exclude(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* /*exception*/) -{ - if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileClass())) - return JSValueMakeUndefined(ctx); - - if (argumentCount < 1) - return JSValueMakeUndefined(ctx); - - if (!JSValueIsObjectOfClass(ctx, arguments[0], ProfileNodeClass())) - return JSValueMakeUndefined(ctx); - - Profile* profile = static_cast<Profile*>(JSObjectGetPrivate(thisObject)); - profile->exclude(static_cast<ProfileNode*>(JSObjectGetPrivate(const_cast<JSObjectRef>(arguments[0])))); - - return JSValueMakeUndefined(ctx); -} - -static JSValueRef restoreAll(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments*/, JSValueRef* /*exception*/) -{ - if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileClass())) - return JSValueMakeUndefined(ctx); - - Profile* profile = static_cast<Profile*>(JSObjectGetPrivate(thisObject)); - profile->restoreAll(); - - return JSValueMakeUndefined(ctx); -} - -static void finalize(JSObjectRef object) -{ - Profile* profile = static_cast<Profile*>(JSObjectGetPrivate(object)); - profileCache().remove(profile); - profile->deref(); -} - -JSClassRef ProfileClass() -{ - static JSStaticValue staticValues[] = { - { "title", getTitleCallback, 0, kJSPropertyAttributeNone }, - { "head", getHeadCallback, 0, kJSPropertyAttributeNone }, - { "uid", getUniqueIdCallback, 0, kJSPropertyAttributeNone }, - { 0, 0, 0, 0 } - }; - - static JSStaticFunction staticFunctions[] = { - { "focus", focus, kJSPropertyAttributeNone }, - { "exclude", exclude, kJSPropertyAttributeNone }, - { "restoreAll", restoreAll, kJSPropertyAttributeNone }, - { 0, 0, 0 } - }; - - static JSClassDefinition classDefinition = { - 0, kJSClassAttributeNone, "Profile", 0, staticValues, staticFunctions, - 0, finalize, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - - static JSClassRef profileClass = JSClassCreate(&classDefinition); - return profileClass; -} - -JSValue toJS(ExecState* exec, Profile* profile) -{ - if (!profile) - return jsNull(); - - JSObject* profileWrapper = profileCache().get(profile); - if (profileWrapper) - return profileWrapper; - - profile->ref(); - profileWrapper = toJS(JSObjectMake(toRef(exec), ProfileClass(), static_cast<void*>(profile))); - profileCache().set(profile, profileWrapper); - return profileWrapper; -} - -} // namespace WebCore - -#endif // ENABLE(JAVASCRIPT_DEBUGGER) diff --git a/WebCore/bindings/js/JavaScriptProfileNode.cpp b/WebCore/bindings/js/JavaScriptProfileNode.cpp deleted file mode 100644 index 7d60b24..0000000 --- a/WebCore/bindings/js/JavaScriptProfileNode.cpp +++ /dev/null @@ -1,236 +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 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 "JavaScriptProfileNode.h" - -#if ENABLE(JAVASCRIPT_DEBUGGER) - -#include "JSDOMBinding.h" -#include <JavaScriptCore/APICast.h> -#include <JavaScriptCore/JSContextRef.h> -#include <JavaScriptCore/JSObjectRef.h> -#include <JavaScriptCore/JSRetainPtr.h> -#include <JavaScriptCore/JSStringRef.h> -#include <profiler/ProfileNode.h> -#include <runtime/JSLock.h> -#include <runtime/JSValue.h> -#include <wtf/StdLibExtras.h> - -using namespace JSC; - -namespace WebCore { - -// Cache - -typedef HashMap<ProfileNode*, JSObject*> ProfileNodeMap; - -static ProfileNodeMap& profileNodeCache() -{ - DEFINE_STATIC_LOCAL(ProfileNodeMap, staticProfileNodes, ()); - return staticProfileNodes; -} - -static JSValueRef getFunctionName(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*) -{ - if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileNodeClass())) - return JSValueMakeUndefined(ctx); - - ProfileNode* profileNode = static_cast<ProfileNode*>(JSObjectGetPrivate(thisObject)); - JSRetainPtr<JSStringRef> functionNameString(Adopt, JSStringCreateWithCharacters(profileNode->functionName().data(), profileNode->functionName().size())); - return JSValueMakeString(ctx, functionNameString.get()); -} - -static JSValueRef getURL(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*) -{ - if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileNodeClass())) - return JSValueMakeUndefined(ctx); - - ProfileNode* profileNode = static_cast<ProfileNode*>(JSObjectGetPrivate(thisObject)); - JSRetainPtr<JSStringRef> urlString(Adopt, JSStringCreateWithCharacters(profileNode->url().data(), profileNode->url().size())); - return JSValueMakeString(ctx, urlString.get()); -} - -static JSValueRef getLineNumber(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*) -{ - if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileNodeClass())) - return JSValueMakeUndefined(ctx); - - ProfileNode* profileNode = static_cast<ProfileNode*>(JSObjectGetPrivate(thisObject)); - return JSValueMakeNumber(ctx, profileNode->lineNumber()); -} - -static JSValueRef getTotalTime(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*) -{ - JSC::JSLock lock(SilenceAssertionsOnly); - - if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileNodeClass())) - return JSValueMakeUndefined(ctx); - - ProfileNode* profileNode = static_cast<ProfileNode*>(JSObjectGetPrivate(thisObject)); - return JSValueMakeNumber(ctx, profileNode->totalTime()); -} - -static JSValueRef getSelfTime(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*) -{ - JSC::JSLock lock(SilenceAssertionsOnly); - - if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileNodeClass())) - return JSValueMakeUndefined(ctx); - - ProfileNode* profileNode = static_cast<ProfileNode*>(JSObjectGetPrivate(thisObject)); - return JSValueMakeNumber(ctx, profileNode->selfTime()); -} - -static JSValueRef getNumberOfCalls(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*) -{ - JSC::JSLock lock(SilenceAssertionsOnly); - - if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileNodeClass())) - return JSValueMakeUndefined(ctx); - - ProfileNode* profileNode = static_cast<ProfileNode*>(JSObjectGetPrivate(thisObject)); - return JSValueMakeNumber(ctx, profileNode->numberOfCalls()); -} - -static JSValueRef getChildren(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef* exception) -{ - JSC::JSLock lock(SilenceAssertionsOnly); - - if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileNodeClass())) - return JSValueMakeUndefined(ctx); - - ProfileNode* profileNode = static_cast<ProfileNode*>(JSObjectGetPrivate(thisObject)); - const Vector<RefPtr<ProfileNode> >& children = profileNode->children(); - - JSObjectRef global = JSContextGetGlobalObject(ctx); - - JSRetainPtr<JSStringRef> arrayString(Adopt, JSStringCreateWithUTF8CString("Array")); - - JSValueRef arrayProperty = JSObjectGetProperty(ctx, global, arrayString.get(), exception); - if (exception && *exception) - return JSValueMakeUndefined(ctx); - - JSObjectRef arrayConstructor = JSValueToObject(ctx, arrayProperty, exception); - if (exception && *exception) - return JSValueMakeUndefined(ctx); - - JSObjectRef result = JSObjectCallAsConstructor(ctx, arrayConstructor, 0, 0, exception); - if (exception && *exception) - return JSValueMakeUndefined(ctx); - - JSRetainPtr<JSStringRef> pushString(Adopt, JSStringCreateWithUTF8CString("push")); - - JSValueRef pushProperty = JSObjectGetProperty(ctx, result, pushString.get(), exception); - if (exception && *exception) - return JSValueMakeUndefined(ctx); - - JSObjectRef pushFunction = JSValueToObject(ctx, pushProperty, exception); - if (exception && *exception) - return JSValueMakeUndefined(ctx); - - ExecState* exec = toJS(ctx); - for (Vector<RefPtr<ProfileNode> >::const_iterator it = children.begin(); it != children.end(); ++it) { - JSValueRef arg0 = toRef(exec, toJS(exec, (*it).get() )); - JSObjectCallAsFunction(ctx, pushFunction, result, 1, &arg0, exception); - if (exception && *exception) - return JSValueMakeUndefined(ctx); - } - - return result; -} - -static JSValueRef getVisible(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*) -{ - JSC::JSLock lock(SilenceAssertionsOnly); - - if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileNodeClass())) - return JSValueMakeUndefined(ctx); - - ProfileNode* profileNode = static_cast<ProfileNode*>(JSObjectGetPrivate(thisObject)); - return JSValueMakeBoolean(ctx, profileNode->visible()); -} - -static JSValueRef getCallUID(JSContextRef ctx, JSObjectRef thisObject, JSStringRef, JSValueRef*) -{ - JSC::JSLock lock(SilenceAssertionsOnly); - - if (!JSValueIsObjectOfClass(ctx, thisObject, ProfileNodeClass())) - return JSValueMakeUndefined(ctx); - - ProfileNode* profileNode = static_cast<ProfileNode*>(JSObjectGetPrivate(thisObject)); - return JSValueMakeNumber(ctx, profileNode->callIdentifier().hash()); -} - -static void finalize(JSObjectRef object) -{ - ProfileNode* profileNode = static_cast<ProfileNode*>(JSObjectGetPrivate(object)); - profileNodeCache().remove(profileNode); - profileNode->deref(); -} - -JSClassRef ProfileNodeClass() -{ - static JSStaticValue staticValues[] = { - { "functionName", getFunctionName, 0, kJSPropertyAttributeNone }, - { "url", getURL, 0, kJSPropertyAttributeNone }, - { "lineNumber", getLineNumber, 0, kJSPropertyAttributeNone }, - { "totalTime", getTotalTime, 0, kJSPropertyAttributeNone }, - { "selfTime", getSelfTime, 0, kJSPropertyAttributeNone }, - { "numberOfCalls", getNumberOfCalls, 0, kJSPropertyAttributeNone }, - { "children", getChildren, 0, kJSPropertyAttributeNone }, - { "visible", getVisible, 0, kJSPropertyAttributeNone }, - { "callUID", getCallUID, 0, kJSPropertyAttributeNone }, - { 0, 0, 0, 0 } - }; - - static JSClassDefinition classDefinition = { - 0, kJSClassAttributeNone, "ProfileNode", 0, staticValues, 0, - 0, finalize, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - - static JSClassRef profileNodeClass = JSClassCreate(&classDefinition); - return profileNodeClass; -} - -JSValue toJS(ExecState* exec, ProfileNode* profileNode) -{ - if (!profileNode) - return jsNull(); - - JSObject* profileNodeWrapper = profileNodeCache().get(profileNode); - if (profileNodeWrapper) - return profileNodeWrapper; - - profileNode->ref(); - - profileNodeWrapper = toJS(JSObjectMake(toRef(exec), ProfileNodeClass(), static_cast<void*>(profileNode))); - profileNodeCache().set(profileNode, profileNodeWrapper); - return profileNodeWrapper; -} - -} // namespace WebCore - -#endif // ENABLE(JAVASCRIPT_DEBUGGER) diff --git a/WebCore/bindings/js/ScheduledAction.cpp b/WebCore/bindings/js/ScheduledAction.cpp index be62bb8..8fc860b 100644 --- a/WebCore/bindings/js/ScheduledAction.cpp +++ b/WebCore/bindings/js/ScheduledAction.cpp @@ -24,7 +24,6 @@ #include "config.h" #include "ScheduledAction.h" -#include "CString.h" #include "DOMWindow.h" #include "Document.h" #include "Frame.h" @@ -55,7 +54,7 @@ PassOwnPtr<ScheduledAction> ScheduledAction::create(ExecState* exec, const ArgLi UString string = v.toString(exec); if (exec->hadException()) return 0; - return new ScheduledAction(string, isolatedWorld); + return new ScheduledAction(ustringToString(string), isolatedWorld); } ArgList argsTail; args.getSlice(2, argsTail); @@ -117,7 +116,7 @@ void ScheduledAction::execute(Document* document) return; RefPtr<Frame> frame = window->impl()->frame(); - if (!frame || !frame->script()->canExecuteScripts()) + if (!frame || !frame->script()->canExecuteScripts(AboutToExecuteScript)) return; frame->script()->setProcessingTimerCallback(true); diff --git a/WebCore/bindings/js/ScriptCallFrame.cpp b/WebCore/bindings/js/ScriptCallFrame.cpp index 09752d1..19ed1ea 100644 --- a/WebCore/bindings/js/ScriptCallFrame.cpp +++ b/WebCore/bindings/js/ScriptCallFrame.cpp @@ -40,7 +40,7 @@ namespace WebCore { ScriptCallFrame::ScriptCallFrame(const UString& functionName, const UString& urlString, int lineNumber, const ArgList& args, unsigned skipArgumentCount) : m_functionName(functionName) - , m_sourceURL(ParsedURLString, urlString) + , m_sourceURL(ParsedURLString, ustringToString(urlString)) , m_lineNumber(lineNumber) { size_t argumentCount = args.size(); diff --git a/WebCore/bindings/js/ScriptCallStack.cpp b/WebCore/bindings/js/ScriptCallStack.cpp index a435588..771141d 100644 --- a/WebCore/bindings/js/ScriptCallStack.cpp +++ b/WebCore/bindings/js/ScriptCallStack.cpp @@ -101,4 +101,9 @@ void ScriptCallStack::initialize() m_initialized = true; } +bool ScriptCallStack::callLocation(String*, int*, String*) +{ + return false; +} + } // namespace WebCore diff --git a/WebCore/bindings/js/ScriptCallStack.h b/WebCore/bindings/js/ScriptCallStack.h index 52362ea..e51d97a 100644 --- a/WebCore/bindings/js/ScriptCallStack.h +++ b/WebCore/bindings/js/ScriptCallStack.h @@ -53,6 +53,7 @@ namespace WebCore { // frame retrieval methods const ScriptCallFrame &at(unsigned); unsigned size(); + static bool callLocation(String*, int*, String*); private: void initialize(); diff --git a/WebCore/bindings/js/ScriptController.cpp b/WebCore/bindings/js/ScriptController.cpp index 171d4dd..b3695b4 100644 --- a/WebCore/bindings/js/ScriptController.cpp +++ b/WebCore/bindings/js/ScriptController.cpp @@ -21,7 +21,6 @@ #include "config.h" #include "ScriptController.h" -#include "CString.h" #include "Event.h" #include "EventNames.h" #include "Frame.h" @@ -37,6 +36,7 @@ #include "ScriptValue.h" #include "Settings.h" #include "StorageNamespace.h" +#include "WebCoreJSClientData.h" #include "XSSAuditor.h" #include "npruntime_impl.h" #include "runtime_root.h" @@ -81,20 +81,36 @@ ScriptController::ScriptController(Frame* frame) ScriptController::~ScriptController() { + disconnectPlatformScriptObjects(); + + // It's likely that destroying m_windowShells will create a lot of garbage. if (!m_windowShells.isEmpty()) { - m_windowShells.clear(); - - // It's likely that releasing the global object has created a lot of garbage. + while (!m_windowShells.isEmpty()) + destroyWindowShell(m_windowShells.begin()->first.get()); gcController().garbageCollectSoon(); } +} - disconnectPlatformScriptObjects(); +void ScriptController::destroyWindowShell(DOMWrapperWorld* world) +{ + ASSERT(m_windowShells.contains(world)); + m_windowShells.remove(world); + world->didDestroyWindowShell(this); +} + +JSDOMWindowShell* ScriptController::createWindowShell(DOMWrapperWorld* world) +{ + ASSERT(!m_windowShells.contains(world)); + JSDOMWindowShell* windowShell = new JSDOMWindowShell(m_frame->domWindow(), world); + m_windowShells.add(world, windowShell); + world->didCreateWindowShell(this); + return windowShell; } ScriptValue ScriptController::evaluateInWorld(const ScriptSourceCode& sourceCode, DOMWrapperWorld* world) { const SourceCode& jsSourceCode = sourceCode.jsSourceCode(); - String sourceURL = jsSourceCode.provider()->url(); + String sourceURL = ustringToString(jsSourceCode.provider()->url()); if (!m_XSSAuditor->canEvaluate(sourceCode.source())) { // This script is not safe to be evaluated. @@ -152,24 +168,9 @@ ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode) return evaluateInWorld(sourceCode, mainThreadNormalWorld()); } -// An DOMWrapperWorld other than the thread's normal world. -class IsolatedWorld : public DOMWrapperWorld { -public: - static PassRefPtr<IsolatedWorld> create(JSGlobalData* globalData) { return adoptRef(new IsolatedWorld(globalData)); } - -protected: - IsolatedWorld(JSGlobalData* globalData) - : DOMWrapperWorld(globalData, false) - { - JSGlobalData::ClientData* clientData = globalData->clientData; - ASSERT(clientData); - static_cast<WebCoreJSClientData*>(clientData)->rememberWorld(this); - } -}; - PassRefPtr<DOMWrapperWorld> ScriptController::createWorld() { - return IsolatedWorld::create(JSDOMWindow::commonJSGlobalData()); + return DOMWrapperWorld::create(JSDOMWindow::commonJSGlobalData()); } void ScriptController::getAllWorlds(Vector<DOMWrapperWorld*>& worlds) @@ -199,7 +200,7 @@ void ScriptController::clearWindowShell() } } - // There is likely to be a lot of garbage now. + // It's likely that resetting our windows created a lot of garbage. gcController().garbageCollectSoon(); } @@ -209,8 +210,8 @@ JSDOMWindowShell* ScriptController::initScript(DOMWrapperWorld* world) JSLock lock(SilenceAssertionsOnly); - JSDOMWindowShell* windowShell = new JSDOMWindowShell(m_frame->domWindow(), world); - m_windowShells.add(world, windowShell); + JSDOMWindowShell* windowShell = createWindowShell(world); + windowShell->window()->updateDocument(); if (Page* page = m_frame->page()) { @@ -317,7 +318,7 @@ void ScriptController::updateSecurityOrigin() Bindings::RootObject* ScriptController::bindingRootObject() { - if (!canExecuteScripts()) + if (!canExecuteScripts(NotAboutToExecuteScript)) return 0; if (!m_bindingRootObject) { @@ -344,7 +345,7 @@ PassRefPtr<Bindings::RootObject> ScriptController::createRootObject(void* native NPObject* ScriptController::windowScriptNPObject() { if (!m_windowScriptNPObject) { - if (canExecuteScripts()) { + if (canExecuteScripts(NotAboutToExecuteScript)) { // JavaScript is enabled, so there is a JavaScript window object. // Return an NPObject bound to the window object. JSC::JSLock lock(SilenceAssertionsOnly); @@ -377,7 +378,7 @@ NPObject* ScriptController::createScriptObjectForPluginElement(HTMLPlugInElement JSObject* ScriptController::jsObjectForPluginElement(HTMLPlugInElement* plugin) { // Can't create JSObjects when JavaScript is disabled - if (!canExecuteScripts()) + if (!canExecuteScripts(NotAboutToExecuteScript)) return 0; // Create a JSObject bound to this element @@ -444,7 +445,7 @@ ScriptValue ScriptController::executeScriptInWorld(DOMWrapperWorld* world, const { ScriptSourceCode sourceCode(script, forceUserGesture ? KURL() : m_frame->loader()->url()); - if (!canExecuteScripts() || isPaused()) + if (!canExecuteScripts(AboutToExecuteScript) || isPaused()) return ScriptValue(); bool wasInExecuteScript = m_inExecuteScript; diff --git a/WebCore/bindings/js/ScriptController.h b/WebCore/bindings/js/ScriptController.h index 1cbb56d..d096c2e 100644 --- a/WebCore/bindings/js/ScriptController.h +++ b/WebCore/bindings/js/ScriptController.h @@ -62,6 +62,11 @@ class XSSAuditor; typedef HashMap<void*, RefPtr<JSC::Bindings::RootObject> > RootObjectMap; +enum ReasonForCallingCanExecuteScripts { + AboutToExecuteScript, + NotAboutToExecuteScript +}; + class ScriptController { friend class ScriptCachedFrameData; typedef WTF::HashMap< RefPtr<DOMWrapperWorld>, JSC::ProtectedPtr<JSDOMWindowShell> > ShellMap; @@ -72,6 +77,9 @@ public: static PassRefPtr<DOMWrapperWorld> createWorld(); + JSDOMWindowShell* createWindowShell(DOMWrapperWorld*); + void destroyWindowShell(DOMWrapperWorld*); + JSDOMWindowShell* windowShell(DOMWrapperWorld* world) { ShellMap::iterator iter = m_windowShells.find(world); @@ -110,7 +118,7 @@ public: bool processingUserGesture(DOMWrapperWorld*) const; bool anyPageIsProcessingUserGesture() const; - bool canExecuteScripts(); + bool canExecuteScripts(ReasonForCallingCanExecuteScripts); // Debugger can be 0 to detach any existing Debugger. void attachDebugger(JSC::Debugger*); // Attaches/detaches in all worlds/window shells. diff --git a/WebCore/bindings/js/JavaScriptProfileNode.h b/WebCore/bindings/js/ScriptControllerBrew.cpp index f01be19..d8d345a 100644 --- a/WebCore/bindings/js/JavaScriptProfileNode.h +++ b/WebCore/bindings/js/ScriptControllerBrew.cpp @@ -1,5 +1,8 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2008 Apple Computer, Inc. + * Copyright (C) 2009 Company 100, Inc. + * + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +13,10 @@ * 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 + * 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 INC. OR + * 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 @@ -23,26 +26,22 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JavaScriptProfileNode_h -#define JavaScriptProfileNode_h - -#if ENABLE(JAVASCRIPT_DEBUGGER) +#include "config.h" +#include "ScriptController.h" -#include <JavaScriptCore/JSBase.h> -#include <runtime/JSValue.h> - -namespace JSC { -class ExecState; -class ProfileNode; -} +#include "Bridge.h" +#include "PluginView.h" +#include "runtime_root.h" namespace WebCore { -JSClassRef ProfileNodeClass(); -JSC::JSValue toJS(JSC::ExecState*, JSC::ProfileNode*); +PassRefPtr<JSC::Bindings::Instance> ScriptController::createScriptInstanceForWidget(WebCore::Widget* widget) +{ + if (!widget->isPluginView()) + return 0; -} // namespace WebCore + return static_cast<PluginView*>(widget)->bindingInstance(); -#endif // ENABLE(JAVASCRIPT_DEBUGGER) +} -#endif +} // namespace WebCore diff --git a/WebCore/bindings/js/ScriptControllerMac.mm b/WebCore/bindings/js/ScriptControllerMac.mm index 208aae8..a895489 100644 --- a/WebCore/bindings/js/ScriptControllerMac.mm +++ b/WebCore/bindings/js/ScriptControllerMac.mm @@ -107,7 +107,7 @@ PassScriptInstance ScriptController::createScriptInstanceForWidget(Widget* widge WebScriptObject* ScriptController::windowScriptObject() { - if (!canExecuteScripts()) + if (!canExecuteScripts(NotAboutToExecuteScript)) return 0; if (!m_windowScriptObject) { diff --git a/WebCore/bindings/js/ScriptDebugServer.cpp b/WebCore/bindings/js/ScriptDebugServer.cpp index 9869775..8f476b4 100644 --- a/WebCore/bindings/js/ScriptDebugServer.cpp +++ b/WebCore/bindings/js/ScriptDebugServer.cpp @@ -1,47 +1,588 @@ /* - * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. * 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 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. + * 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 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 "ScriptDebugServer.h" #if ENABLE(JAVASCRIPT_DEBUGGER) -#include "ScriptDebugServer.h" +#include "DOMWindow.h" +#include "EventLoop.h" +#include "Frame.h" +#include "FrameTree.h" +#include "FrameView.h" +#include "JSDOMWindowCustom.h" +#include "JavaScriptCallFrame.h" +#include "Page.h" +#include "PageGroup.h" +#include "PluginView.h" +#include "ScriptBreakpoint.h" +#include "ScriptController.h" +#include "ScriptDebugListener.h" +#include "ScrollView.h" +#include "Widget.h" +#include <debugger/DebuggerCallFrame.h> +#include <parser/SourceCode.h> +#include <runtime/JSLock.h> +#include <wtf/MainThread.h> +#include <wtf/StdLibExtras.h> +#include <wtf/UnusedParam.h> -#include "JavaScriptDebugServer.h" +using namespace JSC; namespace WebCore { -void ScriptDebugServer::recompileAllJSFunctions() +ScriptDebugServer& ScriptDebugServer::shared() +{ + DEFINE_STATIC_LOCAL(ScriptDebugServer, server, ()); + return server; +} + +ScriptDebugServer::ScriptDebugServer() + : m_callingListeners(false) + , m_pauseOnExceptionsState(DontPauseOnExceptions) + , m_pauseOnNextStatement(false) + , m_paused(false) + , m_doneProcessingDebuggerEvents(true) + , m_breakpointsActivated(true) + , m_pauseOnCallFrame(0) + , m_recompileTimer(this, &ScriptDebugServer::recompileAllJSFunctions) +{ +} + +ScriptDebugServer::~ScriptDebugServer() +{ + deleteAllValues(m_pageListenersMap); +} + +void ScriptDebugServer::addListener(ScriptDebugListener* listener, Page* page) +{ + ASSERT_ARG(listener, listener); + ASSERT_ARG(page, page); + + pair<PageListenersMap::iterator, bool> result = m_pageListenersMap.add(page, 0); + if (result.second) + result.first->second = new ListenerSet; + + ListenerSet* listeners = result.first->second; + listeners->add(listener); + + didAddListener(page); +} + +void ScriptDebugServer::removeListener(ScriptDebugListener* listener, Page* page) +{ + ASSERT_ARG(listener, listener); + ASSERT_ARG(page, page); + + PageListenersMap::iterator it = m_pageListenersMap.find(page); + if (it == m_pageListenersMap.end()) + return; + + ListenerSet* listeners = it->second; + listeners->remove(listener); + if (listeners->isEmpty()) { + m_pageListenersMap.remove(it); + delete listeners; + } + + didRemoveListener(page); + if (!hasListeners()) + didRemoveLastListener(); +} + +void ScriptDebugServer::pageCreated(Page* page) +{ + ASSERT_ARG(page, page); + + if (!hasListenersInterestedInPage(page)) + return; + page->setDebugger(this); +} + +bool ScriptDebugServer::hasListenersInterestedInPage(Page* page) { - JavaScriptDebugServer::shared().recompileAllJSFunctions(); + ASSERT_ARG(page, page); + + if (hasGlobalListeners()) + return true; + + return m_pageListenersMap.contains(page); +} + +void ScriptDebugServer::setBreakpoint(const String& sourceID, unsigned lineNumber, ScriptBreakpoint breakpoint) +{ + intptr_t sourceIDValue = sourceID.toIntPtr(); + if (!sourceIDValue) + return; + BreakpointsMap::iterator it = m_breakpoints.find(sourceIDValue); + if (it == m_breakpoints.end()) + it = m_breakpoints.set(sourceIDValue, SourceBreakpoints()).first; + it->second.set(lineNumber, breakpoint); +} + +void ScriptDebugServer::removeBreakpoint(const String& sourceID, unsigned lineNumber) +{ + intptr_t sourceIDValue = sourceID.toIntPtr(); + if (!sourceIDValue) + return; + BreakpointsMap::iterator it = m_breakpoints.find(sourceIDValue); + if (it != m_breakpoints.end()) + it->second.remove(lineNumber); +} + +bool ScriptDebugServer::hasBreakpoint(intptr_t sourceID, unsigned lineNumber) const +{ + if (!m_breakpointsActivated) + return false; + + BreakpointsMap::const_iterator it = m_breakpoints.find(sourceID); + if (it == m_breakpoints.end()) + return false; + SourceBreakpoints::const_iterator breakIt = it->second.find(lineNumber); + if (breakIt == it->second.end() || !breakIt->second.enabled) + return false; + + // An empty condition counts as no condition which is equivalent to "true". + if (breakIt->second.condition.isEmpty()) + return true; + + JSValue exception; + JSValue result = m_currentCallFrame->evaluate(stringToUString(breakIt->second.condition), exception); + if (exception) { + // An erroneous condition counts as "false". + return false; + } + return result.toBoolean(m_currentCallFrame->scopeChain()->globalObject->globalExec()); +} + +void ScriptDebugServer::clearBreakpoints() +{ + m_breakpoints.clear(); +} + +void ScriptDebugServer::setBreakpointsActivated(bool activated) +{ + m_breakpointsActivated = activated; +} + +void ScriptDebugServer::setPauseOnExceptionsState(PauseOnExceptionsState pause) +{ + m_pauseOnExceptionsState = pause; +} + +void ScriptDebugServer::pauseProgram() +{ + m_pauseOnNextStatement = true; +} + +void ScriptDebugServer::continueProgram() +{ + if (!m_paused) + return; + + m_pauseOnNextStatement = false; + m_doneProcessingDebuggerEvents = true; +} + +void ScriptDebugServer::stepIntoStatement() +{ + if (!m_paused) + return; + + m_pauseOnNextStatement = true; + m_doneProcessingDebuggerEvents = true; +} + +void ScriptDebugServer::stepOverStatement() +{ + if (!m_paused) + return; + + m_pauseOnCallFrame = m_currentCallFrame.get(); + m_doneProcessingDebuggerEvents = true; +} + +void ScriptDebugServer::stepOutOfFunction() +{ + if (!m_paused) + return; + + m_pauseOnCallFrame = m_currentCallFrame ? m_currentCallFrame->caller() : 0; + m_doneProcessingDebuggerEvents = true; +} + +JavaScriptCallFrame* ScriptDebugServer::currentCallFrame() +{ + if (!m_paused) + return 0; + return m_currentCallFrame.get(); +} + +ScriptState* ScriptDebugServer::currentCallFrameState() +{ + if (!m_paused) + return 0; + return m_currentCallFrame->scopeChain()->globalObject->globalExec(); +} + +void ScriptDebugServer::dispatchDidParseSource(const ListenerSet& listeners, const JSC::SourceCode& source) +{ + String sourceID = ustringToString(JSC::UString::from(source.provider()->asID())); + String url = ustringToString(source.provider()->url()); + String data = ustringToString(JSC::UString(source.data(), source.length())); + int firstLine = source.firstLine(); + + Vector<ScriptDebugListener*> copy; + copyToVector(listeners, copy); + for (size_t i = 0; i < copy.size(); ++i) + copy[i]->didParseSource(sourceID, url, data, firstLine); +} + +void ScriptDebugServer::dispatchFailedToParseSource(const ListenerSet& listeners, const SourceCode& source, int errorLine, const String& errorMessage) +{ + String url = ustringToString(source.provider()->url()); + String data = ustringToString(JSC::UString(source.data(), source.length())); + int firstLine = source.firstLine(); + + Vector<ScriptDebugListener*> copy; + copyToVector(listeners, copy); + for (size_t i = 0; i < copy.size(); ++i) + copy[i]->failedToParseSource(url, data, firstLine, errorLine, errorMessage); +} + +static Page* toPage(JSGlobalObject* globalObject) +{ + ASSERT_ARG(globalObject, globalObject); + + JSDOMWindow* window = asJSDOMWindow(globalObject); + Frame* frame = window->impl()->frame(); + return frame ? frame->page() : 0; +} + +void ScriptDebugServer::detach(JSGlobalObject* globalObject) +{ + // If we're detaching from the currently executing global object, manually tear down our + // stack, since we won't get further debugger callbacks to do so. Also, resume execution, + // since there's no point in staying paused once a window closes. + if (m_currentCallFrame && m_currentCallFrame->dynamicGlobalObject() == globalObject) { + m_currentCallFrame = 0; + m_pauseOnCallFrame = 0; + continueProgram(); + } + Debugger::detach(globalObject); +} + +void ScriptDebugServer::sourceParsed(ExecState* exec, const SourceCode& source, int errorLine, const UString& errorMessage) +{ + if (m_callingListeners) + return; + + Page* page = toPage(exec->dynamicGlobalObject()); + if (!page) + return; + + m_callingListeners = true; + + bool isError = errorLine != -1; + + if (hasGlobalListeners()) { + if (isError) + dispatchFailedToParseSource(m_listeners, source, errorLine, ustringToString(errorMessage)); + else + dispatchDidParseSource(m_listeners, source); + } + + if (ListenerSet* pageListeners = m_pageListenersMap.get(page)) { + ASSERT(!pageListeners->isEmpty()); + if (isError) + dispatchFailedToParseSource(*pageListeners, source, errorLine, ustringToString(errorMessage)); + else + dispatchDidParseSource(*pageListeners, source); + } + + m_callingListeners = false; +} + +void ScriptDebugServer::dispatchFunctionToListeners(const ListenerSet& listeners, JavaScriptExecutionCallback callback) +{ + Vector<ScriptDebugListener*> copy; + copyToVector(listeners, copy); + for (size_t i = 0; i < copy.size(); ++i) + (copy[i]->*callback)(); +} + +void ScriptDebugServer::dispatchFunctionToListeners(JavaScriptExecutionCallback callback, Page* page) +{ + if (m_callingListeners) + return; + + m_callingListeners = true; + + ASSERT(hasListeners()); + + dispatchFunctionToListeners(m_listeners, callback); + + if (ListenerSet* pageListeners = m_pageListenersMap.get(page)) { + ASSERT(!pageListeners->isEmpty()); + dispatchFunctionToListeners(*pageListeners, callback); + } + + m_callingListeners = false; +} + +void ScriptDebugServer::setJavaScriptPaused(const PageGroup& pageGroup, bool paused) +{ + setMainThreadCallbacksPaused(paused); + + const HashSet<Page*>& pages = pageGroup.pages(); + + HashSet<Page*>::const_iterator end = pages.end(); + for (HashSet<Page*>::const_iterator it = pages.begin(); it != end; ++it) + setJavaScriptPaused(*it, paused); +} + +void ScriptDebugServer::setJavaScriptPaused(Page* page, bool paused) +{ + ASSERT_ARG(page, page); + + page->setDefersLoading(paused); + + for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext()) + setJavaScriptPaused(frame, paused); +} + +void ScriptDebugServer::setJavaScriptPaused(Frame* frame, bool paused) +{ + ASSERT_ARG(frame, frame); + + if (!frame->script()->canExecuteScripts(NotAboutToExecuteScript)) + return; + + frame->script()->setPaused(paused); + + Document* document = frame->document(); + if (paused) + document->suspendActiveDOMObjects(); + else + document->resumeActiveDOMObjects(); + + setJavaScriptPaused(frame->view(), paused); +} + +void ScriptDebugServer::setJavaScriptPaused(FrameView* view, bool paused) +{ + if (!view) + return; + + const HashSet<RefPtr<Widget> >* children = view->children(); + ASSERT(children); + + HashSet<RefPtr<Widget> >::const_iterator end = children->end(); + for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != end; ++it) { + Widget* widget = (*it).get(); + if (!widget->isPluginView()) + continue; + static_cast<PluginView*>(widget)->setJavaScriptPaused(paused); + } +} + +void ScriptDebugServer::pauseIfNeeded(Page* page) +{ + if (m_paused) + return; + + if (!page || !hasListenersInterestedInPage(page)) + return; + + bool pauseNow = m_pauseOnNextStatement; + pauseNow |= (m_pauseOnCallFrame == m_currentCallFrame); + pauseNow |= (m_currentCallFrame->line() > 0 && hasBreakpoint(m_currentCallFrame->sourceID(), m_currentCallFrame->line())); + if (!pauseNow) + return; + + m_pauseOnCallFrame = 0; + m_pauseOnNextStatement = false; + m_paused = true; + + dispatchFunctionToListeners(&ScriptDebugListener::didPause, page); + + setJavaScriptPaused(page->group(), true); + + TimerBase::fireTimersInNestedEventLoop(); + + EventLoop loop; + m_doneProcessingDebuggerEvents = false; + while (!m_doneProcessingDebuggerEvents && !loop.ended()) + loop.cycle(); + + setJavaScriptPaused(page->group(), false); + + m_paused = false; + + dispatchFunctionToListeners(&ScriptDebugListener::didContinue, page); +} + +void ScriptDebugServer::callEvent(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber) +{ + if (m_paused) + return; + + m_currentCallFrame = JavaScriptCallFrame::create(debuggerCallFrame, m_currentCallFrame, sourceID, lineNumber); + pauseIfNeeded(toPage(debuggerCallFrame.dynamicGlobalObject())); +} + +void ScriptDebugServer::atStatement(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber) +{ + if (m_paused) + return; + + ASSERT(m_currentCallFrame); + if (!m_currentCallFrame) + return; + + m_currentCallFrame->update(debuggerCallFrame, sourceID, lineNumber); + pauseIfNeeded(toPage(debuggerCallFrame.dynamicGlobalObject())); +} + +void ScriptDebugServer::returnEvent(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber) +{ + if (m_paused) + return; + + ASSERT(m_currentCallFrame); + if (!m_currentCallFrame) + return; + + m_currentCallFrame->update(debuggerCallFrame, sourceID, lineNumber); + pauseIfNeeded(toPage(debuggerCallFrame.dynamicGlobalObject())); + + // Treat stepping over a return statement like stepping out. + if (m_currentCallFrame == m_pauseOnCallFrame) + m_pauseOnCallFrame = m_currentCallFrame->caller(); + m_currentCallFrame = m_currentCallFrame->caller(); +} + +void ScriptDebugServer::exception(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber, bool hasHandler) +{ + if (m_paused) + return; + + ASSERT(m_currentCallFrame); + if (!m_currentCallFrame) + return; + + if (m_pauseOnExceptionsState == PauseOnAllExceptions || (m_pauseOnExceptionsState == PauseOnUncaughtExceptions && !hasHandler)) + m_pauseOnNextStatement = true; + + m_currentCallFrame->update(debuggerCallFrame, sourceID, lineNumber); + pauseIfNeeded(toPage(debuggerCallFrame.dynamicGlobalObject())); +} + +void ScriptDebugServer::willExecuteProgram(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber) +{ + if (m_paused) + return; + + m_currentCallFrame = JavaScriptCallFrame::create(debuggerCallFrame, m_currentCallFrame, sourceID, lineNumber); + pauseIfNeeded(toPage(debuggerCallFrame.dynamicGlobalObject())); +} + +void ScriptDebugServer::didExecuteProgram(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber) +{ + if (m_paused) + return; + + ASSERT(m_currentCallFrame); + if (!m_currentCallFrame) + return; + + m_currentCallFrame->update(debuggerCallFrame, sourceID, lineNumber); + pauseIfNeeded(toPage(debuggerCallFrame.dynamicGlobalObject())); + + // Treat stepping over the end of a program like stepping out. + if (m_currentCallFrame == m_pauseOnCallFrame) + m_pauseOnCallFrame = m_currentCallFrame->caller(); + m_currentCallFrame = m_currentCallFrame->caller(); +} + +void ScriptDebugServer::didReachBreakpoint(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber) +{ + if (m_paused) + return; + + ASSERT(m_currentCallFrame); + if (!m_currentCallFrame) + return; + + m_pauseOnNextStatement = true; + m_currentCallFrame->update(debuggerCallFrame, sourceID, lineNumber); + pauseIfNeeded(toPage(debuggerCallFrame.dynamicGlobalObject())); } void ScriptDebugServer::recompileAllJSFunctionsSoon() { - JavaScriptDebugServer::shared().recompileAllJSFunctionsSoon(); + m_recompileTimer.startOneShot(0); +} + +void ScriptDebugServer::recompileAllJSFunctions(Timer<ScriptDebugServer>*) +{ + JSLock lock(SilenceAssertionsOnly); + Debugger::recompileAllJSFunctions(JSDOMWindow::commonJSGlobalData()); +} + +void ScriptDebugServer::didAddListener(Page* page) +{ + recompileAllJSFunctionsSoon(); + + if (page) + page->setDebugger(this); + else + Page::setDebuggerForAllPages(this); +} + +void ScriptDebugServer::didRemoveListener(Page* page) +{ + if (hasGlobalListeners() || (page && hasListenersInterestedInPage(page))) + return; + + recompileAllJSFunctionsSoon(); + + if (page) + page->setDebugger(0); + else + Page::setDebuggerForAllPages(0); +} + +void ScriptDebugServer::didRemoveLastListener() +{ + m_doneProcessingDebuggerEvents = true; } } // namespace WebCore diff --git a/WebCore/bindings/js/ScriptDebugServer.h b/WebCore/bindings/js/ScriptDebugServer.h index 027ffa5..4740585 100644 --- a/WebCore/bindings/js/ScriptDebugServer.h +++ b/WebCore/bindings/js/ScriptDebugServer.h @@ -1,27 +1,30 @@ /* - * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2008 Apple Inc. All rights reserved. * 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 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. + * 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 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 ScriptDebugServer_h @@ -29,14 +32,118 @@ #if ENABLE(JAVASCRIPT_DEBUGGER) -#include <wtf/Noncopyable.h> +#include "PlatformString.h" +#include "ScriptBreakpoint.h" +#include "ScriptState.h" +#include "Timer.h" + +#include <debugger/Debugger.h> +#include <runtime/UString.h> +#include <wtf/HashMap.h> +#include <wtf/HashSet.h> +#include <wtf/RefPtr.h> +namespace JSC { +class DebuggerCallFrame; +class JSGlobalObject; +} namespace WebCore { -class ScriptDebugServer : public Noncopyable { +class Frame; +class FrameView; +class Page; +class PageGroup; +class ScriptDebugListener; +class JavaScriptCallFrame; + +class ScriptDebugServer : JSC::Debugger, public Noncopyable { public: - static void recompileAllJSFunctions(); - static void recompileAllJSFunctionsSoon(); + static ScriptDebugServer& shared(); + + void addListener(ScriptDebugListener*, Page*); + void removeListener(ScriptDebugListener*, Page*); + + void setBreakpoint(const String& sourceID, unsigned lineNumber, ScriptBreakpoint breakpoint); + void removeBreakpoint(const String& sourceID, unsigned lineNumber); + void clearBreakpoints(); + void setBreakpointsActivated(bool activated); + + enum PauseOnExceptionsState { + DontPauseOnExceptions, + PauseOnAllExceptions, + PauseOnUncaughtExceptions + }; + PauseOnExceptionsState pauseOnExceptionsState() const { return m_pauseOnExceptionsState; } + void setPauseOnExceptionsState(PauseOnExceptionsState); + + void pauseProgram(); + void continueProgram(); + void stepIntoStatement(); + void stepOverStatement(); + void stepOutOfFunction(); + + void recompileAllJSFunctionsSoon(); + void recompileAllJSFunctions(Timer<ScriptDebugServer>* = 0); + + JavaScriptCallFrame* currentCallFrame(); + ScriptState* currentCallFrameState(); + + void pageCreated(Page*); + +private: + typedef HashSet<ScriptDebugListener*> ListenerSet; + typedef void (ScriptDebugListener::*JavaScriptExecutionCallback)(); + + ScriptDebugServer(); + ~ScriptDebugServer(); + + bool hasBreakpoint(intptr_t sourceID, unsigned lineNumber) const; + bool hasListeners() const { return !m_listeners.isEmpty() || !m_pageListenersMap.isEmpty(); } + bool hasGlobalListeners() const { return !m_listeners.isEmpty(); } + bool hasListenersInterestedInPage(Page*); + + void setJavaScriptPaused(const PageGroup&, bool paused); + void setJavaScriptPaused(Page*, bool paused); + void setJavaScriptPaused(Frame*, bool paused); + void setJavaScriptPaused(FrameView*, bool paused); + + void dispatchFunctionToListeners(JavaScriptExecutionCallback, Page*); + void dispatchFunctionToListeners(const ListenerSet& listeners, JavaScriptExecutionCallback callback); + void dispatchDidParseSource(const ListenerSet& listeners, const JSC::SourceCode& source); + void dispatchFailedToParseSource(const ListenerSet& listeners, const JSC::SourceCode& source, int errorLine, const String& errorMessage); + + void pauseIfNeeded(Page*); + + virtual void detach(JSC::JSGlobalObject*); + + virtual void sourceParsed(JSC::ExecState*, const JSC::SourceCode&, int errorLine, const JSC::UString& errorMsg); + virtual void callEvent(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineNumber); + virtual void atStatement(const JSC::DebuggerCallFrame&, intptr_t sourceID, int firstLine); + virtual void returnEvent(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineNumber); + virtual void exception(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineNumber, bool hasHandler); + virtual void willExecuteProgram(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineno); + virtual void didExecuteProgram(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineno); + virtual void didReachBreakpoint(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineno); + + void didAddListener(Page*); + void didRemoveListener(Page*); + void didRemoveLastListener(); + + typedef HashMap<Page*, ListenerSet*> PageListenersMap; + typedef HashMap<intptr_t, SourceBreakpoints> BreakpointsMap; + + PageListenersMap m_pageListenersMap; + ListenerSet m_listeners; + bool m_callingListeners; + PauseOnExceptionsState m_pauseOnExceptionsState; + bool m_pauseOnNextStatement; + bool m_paused; + bool m_doneProcessingDebuggerEvents; + bool m_breakpointsActivated; + JavaScriptCallFrame* m_pauseOnCallFrame; + RefPtr<JavaScriptCallFrame> m_currentCallFrame; + BreakpointsMap m_breakpoints; + Timer<ScriptDebugServer> m_recompileTimer; }; } // namespace WebCore diff --git a/WebCore/bindings/js/ScriptEventListener.cpp b/WebCore/bindings/js/ScriptEventListener.cpp index fd45546..01b9060 100644 --- a/WebCore/bindings/js/ScriptEventListener.cpp +++ b/WebCore/bindings/js/ScriptEventListener.cpp @@ -59,12 +59,11 @@ PassRefPtr<JSLazyEventListener> createAttributeEventListener(Node* node, Attribu int lineNumber = 1; String sourceURL; - JSObject* wrapper = 0; // FIXME: We should be able to provide accurate source information for frameless documents, too (e.g. for importing nodes from XMLHttpRequest.responseXML). if (Frame* frame = node->document()->frame()) { ScriptController* scriptController = frame->script(); - if (!scriptController->canExecuteScripts()) + if (!scriptController->canExecuteScripts(AboutToExecuteScript)) return 0; if (!scriptController->xssAuditor()->canCreateInlineEventListener(attr->localName().string(), attr->value())) { @@ -74,13 +73,9 @@ PassRefPtr<JSLazyEventListener> createAttributeEventListener(Node* node, Attribu lineNumber = scriptController->eventHandlerLineNumber(); sourceURL = node->document()->url().string(); - - JSC::JSLock lock(SilenceAssertionsOnly); - JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(node->document(), mainThreadNormalWorld()); - wrapper = asObject(toJS(globalObject->globalExec(), globalObject, node)); } - return JSLazyEventListener::create(attr->localName().string(), eventParameterName(node->isSVGElement()), attr->value(), node, sourceURL, lineNumber, wrapper, mainThreadNormalWorld()); + return JSLazyEventListener::create(attr->localName().string(), eventParameterName(node->isSVGElement()), attr->value(), node, sourceURL, lineNumber, 0, mainThreadNormalWorld()); } PassRefPtr<JSLazyEventListener> createAttributeEventListener(Frame* frame, Attribute* attr) @@ -96,7 +91,7 @@ PassRefPtr<JSLazyEventListener> createAttributeEventListener(Frame* frame, Attri String sourceURL; ScriptController* scriptController = frame->script(); - if (!scriptController->canExecuteScripts()) + if (!scriptController->canExecuteScripts(AboutToExecuteScript)) return 0; if (!scriptController->xssAuditor()->canCreateInlineEventListener(attr->localName().string(), attr->value())) { @@ -118,7 +113,7 @@ String getEventListenerHandlerBody(ScriptExecutionContext* context, ScriptState* JSC::JSObject* jsFunction = jsListener->jsFunction(context); if (!jsFunction) return ""; - return jsFunction->toString(scriptState); + return ustringToString(jsFunction->toString(scriptState)); } } // namespace WebCore diff --git a/WebCore/bindings/js/ScriptFunctionCall.cpp b/WebCore/bindings/js/ScriptFunctionCall.cpp index 5001d3c..e9073b5 100644 --- a/WebCore/bindings/js/ScriptFunctionCall.cpp +++ b/WebCore/bindings/js/ScriptFunctionCall.cpp @@ -60,7 +60,7 @@ void ScriptFunctionCall::appendArgument(const ScriptObject& argument) void ScriptFunctionCall::appendArgument(const ScriptString& argument) { - m_arguments.append(jsString(m_exec, argument)); + m_arguments.append(jsString(m_exec, argument.ustring())); } void ScriptFunctionCall::appendArgument(const ScriptValue& argument) @@ -132,7 +132,7 @@ ScriptValue ScriptFunctionCall::call(bool& hadException, bool reportExceptions) JSLock lock(SilenceAssertionsOnly); - JSValue function = thisObject->get(m_exec, Identifier(m_exec, m_name)); + JSValue function = thisObject->get(m_exec, Identifier(m_exec, stringToUString(m_name))); if (m_exec->hadException()) { if (reportExceptions) reportException(m_exec, m_exec->exception()); @@ -170,7 +170,7 @@ ScriptObject ScriptFunctionCall::construct(bool& hadException, bool reportExcept JSLock lock(SilenceAssertionsOnly); - JSObject* constructor = asObject(thisObject->get(m_exec, Identifier(m_exec, m_name))); + JSObject* constructor = asObject(thisObject->get(m_exec, Identifier(m_exec, stringToUString(m_name)))); if (m_exec->hadException()) { if (reportExceptions) reportException(m_exec, m_exec->exception()); diff --git a/WebCore/bindings/js/ScriptGCEvent.h b/WebCore/bindings/js/ScriptGCEvent.h new file mode 100644 index 0000000..57892e7 --- /dev/null +++ b/WebCore/bindings/js/ScriptGCEvent.h @@ -0,0 +1,51 @@ +/* + * 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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 ScriptGCEvent_h +#define ScriptGCEvent_h + +#if ENABLE(INSPECTOR) + +namespace WebCore { + +class ScriptGCEventListener; + +class ScriptGCEvent +{ +public: + static void addEventListener(ScriptGCEventListener*) { } + static void removeEventListener(ScriptGCEventListener*) { } + static void getHeapSize(size_t&, size_t&) { } +}; + +} // namespace WebCore + +#endif // !ENABLE(INSPECTOR) +#endif // !defined(ScriptGCEvent_h) diff --git a/WebCore/bindings/js/ScriptObject.cpp b/WebCore/bindings/js/ScriptObject.cpp index 7948219..16b9f01 100644 --- a/WebCore/bindings/js/ScriptObject.cpp +++ b/WebCore/bindings/js/ScriptObject.cpp @@ -64,7 +64,7 @@ bool ScriptObject::set(const String& name, const String& value) { JSLock lock(SilenceAssertionsOnly); PutPropertySlot slot; - jsObject()->put(m_scriptState, Identifier(m_scriptState, name), jsString(m_scriptState, value), slot); + jsObject()->put(m_scriptState, Identifier(m_scriptState, stringToUString(name)), jsString(m_scriptState, stringToUString(value)), slot); return handleException(m_scriptState); } diff --git a/WebCore/bindings/js/JavaScriptProfile.h b/WebCore/bindings/js/ScriptProfileNode.h index 7b75b97..b2edcbf 100644 --- a/WebCore/bindings/js/JavaScriptProfile.h +++ b/WebCore/bindings/js/ScriptProfileNode.h @@ -1,5 +1,6 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2010 Apple Inc. All rights reserved. + * 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 @@ -10,10 +11,10 @@ * 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 + * 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 INC. OR + * 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 @@ -23,24 +24,18 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JavaScriptProfile_h -#define JavaScriptProfile_h +#ifndef ScriptProfileNode_h +#define ScriptProfileNode_h #if ENABLE(JAVASCRIPT_DEBUGGER) - -#include <runtime/JSValue.h> - -namespace JSC { -class ExecState; -class Profile; -} +#include <profiler/ProfileNode.h> namespace WebCore { -JSC::JSValue toJS(JSC::ExecState*, JSC::Profile*); +typedef JSC::ProfileNode ScriptProfileNode; } // namespace WebCore #endif // ENABLE(JAVASCRIPT_DEBUGGER) -#endif +#endif // ScriptProfileNode_h diff --git a/WebCore/bindings/js/ScriptProfiler.cpp b/WebCore/bindings/js/ScriptProfiler.cpp index 789e3d3..5121232 100644 --- a/WebCore/bindings/js/ScriptProfiler.cpp +++ b/WebCore/bindings/js/ScriptProfiler.cpp @@ -30,18 +30,19 @@ #include "ScriptProfiler.h" +#include "JSDOMBinding.h" #include <profiler/Profiler.h> namespace WebCore { void ScriptProfiler::start(ScriptState* state, const String& title) { - JSC::Profiler::profiler()->startProfiling(state, title); + JSC::Profiler::profiler()->startProfiling(state, stringToUString(title)); } PassRefPtr<ScriptProfile> ScriptProfiler::stop(ScriptState* state, const String& title) { - return JSC::Profiler::profiler()->stopProfiling(state, title); + return JSC::Profiler::profiler()->stopProfiling(state, stringToUString(title)); } } // namespace WebCore diff --git a/WebCore/bindings/js/ScriptState.cpp b/WebCore/bindings/js/ScriptState.cpp index b9f334a..3edd1bd 100644 --- a/WebCore/bindings/js/ScriptState.cpp +++ b/WebCore/bindings/js/ScriptState.cpp @@ -54,7 +54,7 @@ ScriptState* scriptStateFromNode(DOMWrapperWorld* world, Node* node) Frame* frame = document->frame(); if (!frame) return 0; - if (!frame->script()->canExecuteScripts()) + if (!frame->script()->canExecuteScripts(NotAboutToExecuteScript)) return 0; return frame->script()->globalObject(world)->globalExec(); } diff --git a/WebCore/bindings/js/ScriptState.h b/WebCore/bindings/js/ScriptState.h index 0c7c575..6bef4f7 100644 --- a/WebCore/bindings/js/ScriptState.h +++ b/WebCore/bindings/js/ScriptState.h @@ -33,23 +33,39 @@ #define ScriptState_h #include "JSDOMBinding.h" +#include <runtime/Protect.h> +#include <wtf/Noncopyable.h> namespace WebCore { - class DOMWrapperWorld; - class Frame; - class Node; - class Page; +class DOMWrapperWorld; +class Frame; +class Node; +class Page; - // The idea is to expose "state-like" methods (hadException, and any other - // methods where ExecState just dips into globalData) of JSC::ExecState as a - // separate abstraction. - // For now, the separation is purely by convention. - typedef JSC::ExecState ScriptState; +// The idea is to expose "state-like" methods (hadException, and any other +// methods where ExecState just dips into globalData) of JSC::ExecState as a +// separate abstraction. +// For now, the separation is purely by convention. +typedef JSC::ExecState ScriptState; - ScriptState* mainWorldScriptState(Frame*); +class ScriptStateProtectedPtr : public Noncopyable { +public: + ScriptStateProtectedPtr() { } + ScriptStateProtectedPtr(ScriptState* scriptState) : m_globalObject(scriptState->lexicalGlobalObject()) { } + ScriptState* get() + { + if (m_globalObject) + return m_globalObject->globalExec(); + return 0; + } +private: + JSC::ProtectedPtr<JSC::JSGlobalObject> m_globalObject; +}; - ScriptState* scriptStateFromNode(DOMWrapperWorld*, Node*); - ScriptState* scriptStateFromPage(DOMWrapperWorld*, Page*); +ScriptState* mainWorldScriptState(Frame*); + +ScriptState* scriptStateFromNode(DOMWrapperWorld*, Node*); +ScriptState* scriptStateFromPage(DOMWrapperWorld*, Page*); } // namespace WebCore diff --git a/WebCore/bindings/js/ScriptString.h b/WebCore/bindings/js/ScriptString.h index 18964b8..ad0ae95 100644 --- a/WebCore/bindings/js/ScriptString.h +++ b/WebCore/bindings/js/ScriptString.h @@ -31,6 +31,7 @@ #ifndef ScriptString_h #define ScriptString_h +#include "JSDOMBinding.h" #include "PlatformString.h" #include <runtime/UString.h> #include <runtime/StringBuilder.h> @@ -43,9 +44,12 @@ class ScriptString { public: ScriptString() {} ScriptString(const char* s) : m_str(s) {} + ScriptString(const String& s) : m_str(stringToUString(s)) {} ScriptString(const JSC::UString& s) : m_str(s) {} operator JSC::UString() const { return m_str; } + operator String() const { return ustringToString(m_str); } + const JSC::UString& ustring() const { return m_str; } bool isNull() const { return m_str.isNull(); } size_t size() const { return m_str.size(); } @@ -60,7 +64,7 @@ public: { JSC::StringBuilder buffer; buffer.append(m_str); - buffer.append(s); + buffer.append(stringToUString(s)); m_str = buffer.build(); return *this; } diff --git a/WebCore/bindings/js/ScriptValue.cpp b/WebCore/bindings/js/ScriptValue.cpp index 005c329..a52024d 100644 --- a/WebCore/bindings/js/ScriptValue.cpp +++ b/WebCore/bindings/js/ScriptValue.cpp @@ -50,7 +50,7 @@ bool ScriptValue::getString(ScriptState* scriptState, String& result) const UString ustring; if (!m_value.get().getString(scriptState, ustring)) return false; - result = ustring; + result = ustringToString(ustring); return true; } diff --git a/WebCore/bindings/js/ScriptValue.h b/WebCore/bindings/js/ScriptValue.h index 9ccb7ac..f4f9c68 100644 --- a/WebCore/bindings/js/ScriptValue.h +++ b/WebCore/bindings/js/ScriptValue.h @@ -31,14 +31,15 @@ #ifndef ScriptValue_h #define ScriptValue_h +#include "JSDOMBinding.h" #include "PlatformString.h" #include "ScriptState.h" +#include <runtime/JSValue.h> #include <runtime/Protect.h> #include <wtf/PassRefPtr.h> namespace WebCore { -class String; class SerializedScriptValue; class ScriptValue { @@ -48,7 +49,7 @@ public: JSC::JSValue jsValue() const { return m_value.get(); } bool getString(ScriptState*, String& result) const; - String toString(ScriptState* scriptState) const { return m_value.get().toString(scriptState); } + String toString(ScriptState* scriptState) const { return ustringToString(m_value.get().toString(scriptState)); } bool isEqual(ScriptState*, const ScriptValue&) const; bool isNull() const; bool isUndefined() const; @@ -58,6 +59,8 @@ public: PassRefPtr<SerializedScriptValue> serialize(ScriptState*); static ScriptValue deserialize(ScriptState*, SerializedScriptValue*); + static ScriptValue undefined() { return ScriptValue(JSC::jsUndefined()); } + private: JSC::ProtectedJSValue m_value; }; diff --git a/WebCore/bindings/js/ScriptWrappable.h b/WebCore/bindings/js/ScriptWrappable.h index d70cab7..5e99c1c 100644 --- a/WebCore/bindings/js/ScriptWrappable.h +++ b/WebCore/bindings/js/ScriptWrappable.h @@ -31,11 +31,33 @@ #ifndef ScriptWrappable_h #define ScriptWrappable_h +#include "JSDOMWrapper.h" +#include <runtime/WeakGCPtr.h> + namespace WebCore { class ScriptWrappable { public: - ScriptWrappable() { } + ScriptWrappable() : m_wrapper(0) { } + + DOMObject* wrapper() const + { + return m_wrapper.get(); + } + + void setWrapper(DOMObject* wrapper) + { + ASSERT(wrapper); + m_wrapper = wrapper; + } + + void clearWrapper(DOMObject* wrapper) + { + m_wrapper.clear(wrapper); + } + +private: + JSC::WeakGCPtr<DOMObject> m_wrapper; }; } // namespace WebCore diff --git a/WebCore/bindings/js/SerializedScriptValue.cpp b/WebCore/bindings/js/SerializedScriptValue.cpp index fbf8899..e761480 100644 --- a/WebCore/bindings/js/SerializedScriptValue.cpp +++ b/WebCore/bindings/js/SerializedScriptValue.cpp @@ -56,7 +56,7 @@ public: void set(const Identifier& propertyName, const SerializedScriptValueData& value) { ASSERT(m_names.size() == m_values.size()); - m_names.append(String(propertyName.ustring()).crossThreadString().impl()); + m_names.append(identifierToString(propertyName).crossThreadString().impl()); m_values.append(value); } @@ -554,7 +554,7 @@ struct SerializingTreeWalker : public BaseWalker { return SerializedScriptValueData(value); if (value.isString()) - return SerializedScriptValueData(asString(value)->value(m_exec)); + return SerializedScriptValueData(ustringToString(asString(value)->value(m_exec))); if (value.isNumber()) return SerializedScriptValueData(SerializedScriptValueData::NumberType, value.uncheckedGetNumber()); @@ -777,7 +777,7 @@ struct DeserializingTreeWalker : public BaseWalker { void putProperty(JSObject* object, const RefPtr<StringImpl> propertyName, JSValue value) { - object->putDirect(Identifier(m_exec, String(propertyName)), value); + object->putDirect(Identifier(m_exec, stringToUString(String(propertyName))), value); } bool startArray(RefPtr<SerializedArray>, JSArray* outArray) diff --git a/WebCore/bindings/js/StringSourceProvider.h b/WebCore/bindings/js/StringSourceProvider.h index 770c4fc..478c1d1 100644 --- a/WebCore/bindings/js/StringSourceProvider.h +++ b/WebCore/bindings/js/StringSourceProvider.h @@ -29,6 +29,7 @@ #ifndef StringSourceProvider_h #define StringSourceProvider_h +#include "JSDOMBinding.h" #include "ScriptSourceProvider.h" #include <parser/SourceCode.h> @@ -45,7 +46,7 @@ namespace WebCore { private: StringSourceProvider(const String& source, const String& url) - : ScriptSourceProvider(url) + : ScriptSourceProvider(stringToUString(url)) , m_source(source) { } diff --git a/WebCore/bindings/js/WebCoreJSClientData.h b/WebCore/bindings/js/WebCoreJSClientData.h new file mode 100644 index 0000000..5d03328 --- /dev/null +++ b/WebCore/bindings/js/WebCoreJSClientData.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2007 Samuel Weinig <sam@webkit.org> + * Copyright (C) 2009 Google, Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef WebCoreJSClientData_h +#define WebCoreJSClientData_h + +#include "DOMWrapperWorld.h" +#include "DOMObjectHashTableMap.h" +#include <wtf/Noncopyable.h> +#include <wtf/HashSet.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +class WebCoreJSClientData : public JSC::JSGlobalData::ClientData, public Noncopyable { + friend class JSGlobalDataWorldIterator; + friend void initNormalWorldClientData(JSC::JSGlobalData*); + +public: + virtual ~WebCoreJSClientData() + { + ASSERT(m_worldSet.contains(m_normalWorld.get())); + ASSERT(m_worldSet.size() == 1); + ASSERT(m_normalWorld->hasOneRef()); + m_normalWorld.clear(); + ASSERT(m_worldSet.isEmpty()); + } + + DOMWrapperWorld* normalWorld() { return m_normalWorld.get(); } + + void getAllWorlds(Vector<DOMWrapperWorld*>& worlds) + { + copyToVector(m_worldSet, worlds); + } + + 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: + HashSet<DOMWrapperWorld*> m_worldSet; + RefPtr<DOMWrapperWorld> m_normalWorld; +}; + +inline void initNormalWorldClientData(JSC::JSGlobalData* globalData) +{ + WebCoreJSClientData* webCoreJSClientData = new WebCoreJSClientData; + globalData->clientData = webCoreJSClientData; // ~JSGlobalData deletes this pointer. + webCoreJSClientData->m_normalWorld = DOMWrapperWorld::create(globalData, true); +} + +} // namespace WebCore + +#endif // WebCoreJSClientData_h diff --git a/WebCore/bindings/js/WorkerScriptController.cpp b/WebCore/bindings/js/WorkerScriptController.cpp index adcc089..85d6861 100644 --- a/WebCore/bindings/js/WorkerScriptController.cpp +++ b/WebCore/bindings/js/WorkerScriptController.cpp @@ -30,11 +30,11 @@ #include "WorkerScriptController.h" -#include "JSDOMBinding.h" #include "JSDedicatedWorkerContext.h" #include "JSSharedWorkerContext.h" #include "ScriptSourceCode.h" #include "ScriptValue.h" +#include "WebCoreJSClientData.h" #include "WorkerContext.h" #include "WorkerObjectProxy.h" #include "WorkerThread.h" @@ -48,11 +48,11 @@ using namespace JSC; namespace WebCore { WorkerScriptController::WorkerScriptController(WorkerContext* workerContext) - : m_globalData(JSGlobalData::create()) + : m_globalData(JSGlobalData::create(ThreadStackTypeSmall)) , m_workerContext(workerContext) , m_executionForbidden(false) { - m_globalData->clientData = new WebCoreJSClientData(m_globalData.get()); + initNormalWorldClientData(m_globalData.get()); } WorkerScriptController::~WorkerScriptController() @@ -136,15 +136,16 @@ void WorkerScriptController::setException(ScriptValue exception) m_workerContextWrapper->globalExec()->setException(exception.jsValue()); } -void WorkerScriptController::forbidExecution() +void WorkerScriptController::forbidExecution(ForbidExecutionOption option) { - // This function is called from another thread. + // This function may be called from another thread. // Mutex protection for m_executionForbidden is needed to guarantee that the value is synchronized between processors, because // if it were not, the worker could re-enter JSC::evaluate(), but with timeout already reset. - // It is not critical for Interpreter::m_timeoutTime to be synchronized, we just rely on it reaching the worker thread's processor sooner or later. + // It is not critical for Terminator::m_shouldTerminate to be synchronized, we just rely on it reaching the worker thread's processor sooner or later. MutexLocker lock(m_sharedDataMutex); m_executionForbidden = true; - m_globalData->timeoutChecker.setTimeoutInterval(1); // 1ms is the smallest timeout that can be set. + if (option == TerminateRunningScript) + m_globalData->terminator.terminateSoon(); } } // namespace WebCore diff --git a/WebCore/bindings/js/WorkerScriptController.h b/WebCore/bindings/js/WorkerScriptController.h index c820cd9..38c3c30 100644 --- a/WebCore/bindings/js/WorkerScriptController.h +++ b/WebCore/bindings/js/WorkerScriptController.h @@ -52,6 +52,9 @@ namespace WebCore { JSWorkerContext* workerContextWrapper() { + if (m_executionForbidden) + return 0; + initScriptIfNeeded(); return m_workerContextWrapper; } @@ -61,7 +64,8 @@ namespace WebCore { void setException(ScriptValue); - void forbidExecution(); + enum ForbidExecutionOption { TerminateRunningScript, LetRunningScriptFinish }; + void forbidExecution(ForbidExecutionOption); JSC::JSGlobalData* globalData() { return m_globalData.get(); } |