diff options
Diffstat (limited to 'WebCore/bindings')
301 files changed, 9432 insertions, 4469 deletions
diff --git a/WebCore/bindings/ScriptControllerBase.cpp b/WebCore/bindings/ScriptControllerBase.cpp index abe96ee..41d2e0a 100644 --- a/WebCore/bindings/ScriptControllerBase.cpp +++ b/WebCore/bindings/ScriptControllerBase.cpp @@ -31,14 +31,17 @@ namespace WebCore { -bool ScriptController::canExecuteScripts() +bool ScriptController::canExecuteScripts(ReasonForCallingCanExecuteScripts reason) { // FIXME: We should get this information from the document instead of the frame. if (m_frame->loader()->isSandboxed(SandboxScripts)) return false; Settings* settings = m_frame->settings(); - return m_frame->loader()->client()->allowJavaScript(settings && settings->isJavaScriptEnabled()); + const bool allowed = m_frame->loader()->client()->allowJavaScript(settings && settings->isJavaScriptEnabled()); + if (!allowed && reason == AboutToExecuteScript) + m_frame->loader()->client()->didNotAllowScript(); + return allowed; } ScriptValue ScriptController::executeScript(const String& script, bool forceUserGesture) @@ -48,7 +51,7 @@ ScriptValue ScriptController::executeScript(const String& script, bool forceUser ScriptValue ScriptController::executeScript(const ScriptSourceCode& sourceCode) { - if (!canExecuteScripts() || isPaused()) + if (!canExecuteScripts(AboutToExecuteScript) || isPaused()) return ScriptValue(); bool wasInExecuteScript = m_inExecuteScript; @@ -98,7 +101,7 @@ bool ScriptController::executeIfJavaScriptURL(const KURL& url, bool userGesture, // synchronously can cause crashes: // http://bugs.webkit.org/show_bug.cgi?id=16782 if (replaceDocument) - m_frame->loader()->replaceDocument(scriptResult); + m_frame->loader()->writer()->replaceDocument(scriptResult); return true; } diff --git a/WebCore/bindings/generic/BindingDOMWindow.h b/WebCore/bindings/generic/BindingDOMWindow.h index d6d3087..b46bdf9 100644 --- a/WebCore/bindings/generic/BindingDOMWindow.h +++ b/WebCore/bindings/generic/BindingDOMWindow.h @@ -69,12 +69,6 @@ Frame* BindingDOMWindow<Binding>::createWindow(State<Binding>* state, ASSERT(callingFrame); ASSERT(enteredFrame); - if (Document* callingDocument = callingFrame->document()) { - // Sandboxed iframes cannot open new auxiliary browsing contexts. - if (callingDocument->securityOrigin()->isSandboxed(SandboxNavigation)) - return 0; - } - ResourceRequest request; // For whatever reason, Firefox uses the entered frame to determine diff --git a/WebCore/bindings/generic/RuntimeEnabledFeatures.cpp b/WebCore/bindings/generic/RuntimeEnabledFeatures.cpp index 1b09518..6ba85da 100644 --- a/WebCore/bindings/generic/RuntimeEnabledFeatures.cpp +++ b/WebCore/bindings/generic/RuntimeEnabledFeatures.cpp @@ -44,6 +44,8 @@ bool RuntimeEnabledFeatures::isWebkitNotificationsEnabled = false; bool RuntimeEnabledFeatures::isApplicationCacheEnabled = true; bool RuntimeEnabledFeatures::isGeolocationEnabled = true; bool RuntimeEnabledFeatures::isIndexedDBEnabled = false; +bool RuntimeEnabledFeatures::isWebGLEnabled = false; +bool RuntimeEnabledFeatures::isPushStateEnabled = false; #if ENABLE(VIDEO) diff --git a/WebCore/bindings/generic/RuntimeEnabledFeatures.h b/WebCore/bindings/generic/RuntimeEnabledFeatures.h index 6f0f78f..37dceff 100644 --- a/WebCore/bindings/generic/RuntimeEnabledFeatures.h +++ b/WebCore/bindings/generic/RuntimeEnabledFeatures.h @@ -77,6 +77,23 @@ public: static bool openDatabaseEnabled(); #endif +#if ENABLE(3D_CANVAS) + static void setWebGLEnabled(bool isEnabled) { isWebGLEnabled = isEnabled; } + static bool webGLRenderingContextEnabled() { return isWebGLEnabled; } + static bool webGLArrayBufferEnabled() { return isWebGLEnabled; } + static bool webGLByteArrayEnabled() { return isWebGLEnabled; } + static bool webGLUnsignedByteArrayEnabled() { return isWebGLEnabled; } + static bool webGLShortArrayEnabled() { return isWebGLEnabled; } + static bool webGLUnsignedShortArrayEnabled() { return isWebGLEnabled; } + static bool webGLIntArrayEnabled() { return isWebGLEnabled; } + static bool webGLUnsignedIntArrayEnabled() { return isWebGLEnabled; } + static bool webGLFloatArrayEnabled() { return isWebGLEnabled; } +#endif + + static void setPushStateEnabled(bool isEnabled) { isPushStateEnabled = isEnabled; } + static bool pushStateEnabled() { return isPushStateEnabled; } + static bool replaceStateEnabled() { return isPushStateEnabled; } + private: // Never instantiate. RuntimeEnabledFeatures() { } @@ -87,6 +104,8 @@ private: static bool isApplicationCacheEnabled; static bool isGeolocationEnabled; static bool isIndexedDBEnabled; + static bool isWebGLEnabled; + static bool isPushStateEnabled; }; } // namespace WebCore diff --git a/WebCore/bindings/gobject/ConvertToUTF8String.cpp b/WebCore/bindings/gobject/ConvertToUTF8String.cpp new file mode 100644 index 0000000..57010fa --- /dev/null +++ b/WebCore/bindings/gobject/ConvertToUTF8String.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2008 Luke Kenneth Casson Leighton <lkcl@lkcl.net> + * Copyright (C) 2010 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "ConvertToUTF8String.h" + +#include "KURL.h" +#include "PlatformString.h" +#include <wtf/text/CString.h> + +#include <glib.h> + +gchar* convertToUTF8String(WebCore::String const& s) +{ + return g_strdup(s.utf8().data()); +} + +gchar* convertToUTF8String(WebCore::KURL const& s) +{ + return g_strdup(s.string().utf8().data()); +} + diff --git a/WebCore/bindings/gobject/ConvertToUTF8String.h b/WebCore/bindings/gobject/ConvertToUTF8String.h new file mode 100644 index 0000000..02b6416 --- /dev/null +++ b/WebCore/bindings/gobject/ConvertToUTF8String.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2008 Luke Kenneth Casson Leighton <lkcl@lkcl.net> + * Copyright (C) 2010 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef ConvertToUTF8String_h +#define ConvertToUTF8String_h + +namespace WebCore { +class String; +class KURL; +} + +typedef char gchar; + +gchar* convertToUTF8String(WebCore::String const& s); +gchar* convertToUTF8String(WebCore::KURL const& s); + +#endif /* ConvertToUTF8String_h */ diff --git a/WebCore/bindings/gobject/WebKitDOMBinding.cpp b/WebCore/bindings/gobject/WebKitDOMBinding.cpp new file mode 100644 index 0000000..1f900c3 --- /dev/null +++ b/WebCore/bindings/gobject/WebKitDOMBinding.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007 Samuel Weinig <sam@webkit.org> + * Copyright (C) 2008 Luke Kenneth Casson Leighton <lkcl@lkcl.net> + * Copyright (C) 2008 Martin Soto <soto@freedesktop.org> + * Copyright (C) 2009, 2010 Igalia S.L. + * + * 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 "WebKitDOMBinding.h" + +#include "Event.h" +#include "EventException.h" +#include "HTMLNames.h" +#include "WebKitDOMNode.h" +#include "WebKitDOMNodePrivate.h" + +namespace WebKit { + +using namespace WebCore; +using namespace WebCore::HTMLNames; + +// DOMObjectCache + +typedef HashMap<void*, gpointer> DOMObjectMap; + +static DOMObjectMap& domObjects() +{ + static DOMObjectMap staticDOMObjects; + return staticDOMObjects; +} + +gpointer DOMObjectCache::get(void* objectHandle) +{ + return domObjects().get(objectHandle); +} + +gpointer DOMObjectCache::put(void* objectHandle, gpointer wrapper) +{ + domObjects().set(objectHandle, wrapper); + return wrapper; +} + +void DOMObjectCache::forget(void* objectHandle) +{ + domObjects().take(objectHandle); +} + +// kit methods + +static gpointer createWrapper(Node* node) +{ + ASSERT(node); + + gpointer wrappedNode = 0; + + if (node->nodeType()) + wrappedNode = wrapNode(node); + + return DOMObjectCache::put(node, wrappedNode); +} + +gpointer kit(Node* node) +{ + if (!node) + return 0; + + gpointer kitNode = DOMObjectCache::get(node); + if (kitNode) + return kitNode; + + return createWrapper(node); +} + +} // namespace WebKit diff --git a/WebCore/bindings/gobject/WebKitDOMBinding.h b/WebCore/bindings/gobject/WebKitDOMBinding.h new file mode 100644 index 0000000..f6efa46 --- /dev/null +++ b/WebCore/bindings/gobject/WebKitDOMBinding.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007 Samuel Weinig <sam@webkit.org> + * Copyright (C) 2008 Luke Kenneth Casson Leighton <lkcl@lkcl.net> + * Copyright (C) 2008 Martin Soto <soto@freedesktop.org> + * Copyright (C) 2009-2010 Igalia S.L. + * + * 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 WebKitDOMBinding_h +#define WebKitDOMBinding_h + +#include <glib.h> + +namespace WebCore { +class Node; +} // namespace WebCore + +namespace WebKit { +gpointer kit(WebCore::Node* node); + +class DOMObjectCache { +public: + static gpointer get(void* objectHandle); + static gpointer put(void* objectHandle, gpointer wrapper); + static void forget(void* objectHandle); +}; +} // namespace WebKit + +#endif // WebKitDOMBinding_h diff --git a/WebCore/bindings/gobject/WebKitDOMObject.cpp b/WebCore/bindings/gobject/WebKitDOMObject.cpp new file mode 100644 index 0000000..fc8a874 --- /dev/null +++ b/WebCore/bindings/gobject/WebKitDOMObject.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2008 Luke Kenneth Casson Leighton <lkcl@lkcl.net> + * Copyright (C) 2008 Martin Soto <soto@freedesktop.org> + * Copyright (C) 2008 Alp Toker <alp@atoker.com> + * Copyright (C) 2008 Apple Inc. + * Copyright (C) 2009 Igalia S.L. + */ +#include "config.h" +#include "WebKitDOMObject.h" + +#include "glib-object.h" +#include "WebKitDOMBinding.h" + +G_DEFINE_TYPE(WebKitDOMObject, webkit_dom_object, G_TYPE_OBJECT); + +static void webkit_dom_object_init(WebKitDOMObject* object) +{ +} + +static void webkit_dom_object_class_init(WebKitDOMObjectClass* klass) +{ +} + diff --git a/WebCore/bindings/gobject/WebKitDOMObject.h b/WebCore/bindings/gobject/WebKitDOMObject.h new file mode 100644 index 0000000..b99c57c --- /dev/null +++ b/WebCore/bindings/gobject/WebKitDOMObject.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2008 Luke Kenneth Casson Leighton <lkcl@lkcl.net> + * Copyright (C) 2008 Martin Soto <soto@freedesktop.org> + * Copyright (C) 2008 Alp Toker <alp@atoker.com> + * Copyright (C) 2008 Apple Inc. + * Copyright (C) 2009 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef WebKitDOMObject_h +#define WebKitDOMObject_h + +#include "glib-object.h" +#include "webkit/webkitdomdefines.h" +#include <webkit/webkitdefines.h> + +G_BEGIN_DECLS + +#define WEBKIT_TYPE_DOM_OBJECT (webkit_dom_object_get_type()) +#define WEBKIT_DOM_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_DOM_OBJECT, WebKitDOMObject)) +#define WEBKIT_DOM_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_DOM_OBJECT, WebKitDOMObjectClass)) +#define WEBKIT_IS_DOM_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_DOM_OBJECT)) +#define WEBKIT_IS_DOM_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_DOM_OBJECT)) +#define WEBKIT_DOM_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_DOM_OBJECT, WebKitDOMObjectClass)) + +typedef struct _WebKitDOMObjectPrivate WebKitDOMObjectPrivate; + +struct _WebKitDOMObject { + GObject parentInstance; + + gpointer coreObject; +}; + +struct _WebKitDOMObjectClass { + GObjectClass parentClass; +}; + +WEBKIT_API GType +webkit_dom_object_get_type(void); + +G_END_DECLS + +#endif /* WebKitDOMObject_h */ 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/v8/custom/V8ScreenCustom.cpp b/WebCore/bindings/js/JSDOMFormDataCustom.cpp index 98d9dd7..830db6b 100644 --- a/WebCore/bindings/v8/custom/V8ScreenCustom.cpp +++ b/WebCore/bindings/js/JSDOMFormDataCustom.cpp @@ -29,24 +29,28 @@ */ #include "config.h" -#include "V8Screen.h" +#include "JSDOMFormData.h" -#include "V8DOMWindow.h" -#include "V8DOMWrapper.h" +#include "DOMFormData.h" +#include "JSBlob.h" +#include <runtime/Error.h> + +using namespace JSC; namespace WebCore { -v8::Handle<v8::Value> toV8(Screen* impl) +JSValue JSDOMFormData::append(ExecState* exec, const ArgList& args) { - if (!impl) - return v8::Null(); - v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(impl); - if (wrapper.IsEmpty()) { - wrapper = V8Screen::wrap(impl); - if (!wrapper.IsEmpty()) - V8DOMWrapper::setHiddenWindowReference(impl->frame(), V8DOMWindow::screenIndex, wrapper); + 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 wrapper; + + 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/v8/custom/V8IDBRequestCustom.cpp b/WebCore/bindings/js/ScriptGCEvent.h index ccf4d0e..57892e7 100644 --- a/WebCore/bindings/v8/custom/V8IDBRequestCustom.cpp +++ b/WebCore/bindings/js/ScriptGCEvent.h @@ -28,26 +28,24 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" +#ifndef ScriptGCEvent_h +#define ScriptGCEvent_h -#if ENABLE(INDEXED_DATABASE) -#include "V8IDBRequest.h" - -#include "SerializedScriptValue.h" -#include "V8Proxy.h" +#if ENABLE(INSPECTOR) namespace WebCore { -v8::Handle<v8::Value> V8IDBRequest::resultAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) -{ - IDBRequest* request = V8IDBRequest::toNative(info.Holder()); - SerializedScriptValue* result = request->result(); - if (!result) - return v8::Null(); +class ScriptGCEventListener; - return result->deserialize(); -} +class ScriptGCEvent +{ +public: + static void addEventListener(ScriptGCEventListener*) { } + static void removeEventListener(ScriptGCEventListener*) { } + static void getHeapSize(size_t&, size_t&) { } +}; } // namespace WebCore -#endif +#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(); } diff --git a/WebCore/bindings/objc/DOM.mm b/WebCore/bindings/objc/DOM.mm index 907961f..378efe2 100644 --- a/WebCore/bindings/objc/DOM.mm +++ b/WebCore/bindings/objc/DOM.mm @@ -37,6 +37,7 @@ #import "Frame.h" #import "HTMLElement.h" #import "HTMLNames.h" +#import "Image.h" #import "NodeFilter.h" #import "RenderImage.h" #import "WebScriptObjectPrivate.h" diff --git a/WebCore/bindings/objc/WebScriptObject.mm b/WebCore/bindings/objc/WebScriptObject.mm index d7bc90c..618459a 100644 --- a/WebCore/bindings/objc/WebScriptObject.mm +++ b/WebCore/bindings/objc/WebScriptObject.mm @@ -33,6 +33,9 @@ #import "Frame.h" #import "JSDOMWindow.h" #import "JSDOMWindowCustom.h" +#import "JSHTMLElement.h" +#import "JSPluginElementFunctions.h" +#import "ObjCRuntimeObject.h" #import "PlatformString.h" #import "StringSourceProvider.h" #import "WebCoreObjCExtras.h" @@ -286,7 +289,7 @@ static void getListFromNSArray(ExecState *exec, NSArray *array, RootObject* root ExecState* exec = [self _rootObject]->globalObject()->globalExec(); ASSERT(!exec->hadException()); - JSValue function = [self _imp]->get(exec, Identifier(exec, String(name))); + JSValue function = [self _imp]->get(exec, Identifier(exec, stringToUString(String(name)))); CallData callData; CallType callType = function.getCallData(callData); if (callType == CallTypeNone) @@ -363,7 +366,7 @@ static void getListFromNSArray(ExecState *exec, NSArray *array, RootObject* root JSLock lock(SilenceAssertionsOnly); PutPropertySlot slot; - [self _imp]->put(exec, Identifier(exec, String(key)), convertObjcValueToValue(exec, &value, ObjcObjectType, [self _rootObject]), slot); + [self _imp]->put(exec, Identifier(exec, stringToUString(String(key))), convertObjcValueToValue(exec, &value, ObjcObjectType, [self _rootObject]), slot); if (exec->hadException()) { addExceptionToConsole(exec); @@ -388,7 +391,7 @@ static void getListFromNSArray(ExecState *exec, NSArray *array, RootObject* root // leaving the lock permanently held JSLock lock(SilenceAssertionsOnly); - JSValue result = [self _imp]->get(exec, Identifier(exec, String(key))); + JSValue result = [self _imp]->get(exec, Identifier(exec, stringToUString(String(key)))); if (exec->hadException()) { addExceptionToConsole(exec); @@ -417,7 +420,7 @@ static void getListFromNSArray(ExecState *exec, NSArray *array, RootObject* root ASSERT(!exec->hadException()); JSLock lock(SilenceAssertionsOnly); - [self _imp]->deleteProperty(exec, Identifier(exec, String(key))); + [self _imp]->deleteProperty(exec, Identifier(exec, stringToUString(String(key)))); if (exec->hadException()) { addExceptionToConsole(exec); @@ -508,18 +511,17 @@ static void getListFromNSArray(ExecState *exec, NSArray *array, RootObject* root { if (value.isObject()) { JSObject* object = asObject(value); - ExecState* exec = rootObject->globalObject()->globalExec(); JSLock lock(SilenceAssertionsOnly); - - if (object->classInfo() != &RuntimeObjectImp::s_info) { - JSValue runtimeObject = object->get(exec, Identifier(exec, "__apple_runtime_object")); - if (runtimeObject && runtimeObject.isObject()) - object = asObject(runtimeObject); - } - if (object->classInfo() == &RuntimeObjectImp::s_info) { - RuntimeObjectImp* imp = static_cast<RuntimeObjectImp*>(object); - ObjcInstance *instance = static_cast<ObjcInstance*>(imp->getInternalInstance()); + if (object->inherits(&JSHTMLElement::s_info)) { + // Plugin elements cache the instance internally. + HTMLElement* el = static_cast<JSHTMLElement*>(object)->impl(); + ObjcInstance* instance = static_cast<ObjcInstance*>(pluginInstance(el)); + if (instance) + return instance->getObject(); + } else if (object->inherits(&ObjCRuntimeObject::s_info)) { + ObjCRuntimeObject* runtimeObject = static_cast<ObjCRuntimeObject*>(object); + ObjcInstance* instance = runtimeObject->getInternalObjCInstance(); if (instance) return instance->getObject(); return nil; diff --git a/WebCore/bindings/scripts/CodeGenerator.pm b/WebCore/bindings/scripts/CodeGenerator.pm index 506e8ea..487a4b3 100644 --- a/WebCore/bindings/scripts/CodeGenerator.pm +++ b/WebCore/bindings/scripts/CodeGenerator.pm @@ -17,7 +17,7 @@ # Library General Public License for more details. # # You should have received a copy of the GNU Library General Public License -# aint with this library; see the file COPYING.LIB. If not, write to +# along with this library; see the file COPYING.LIB. If not, write to # the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, # Boston, MA 02110-1301, USA. # diff --git a/WebCore/bindings/scripts/CodeGeneratorGObject.pm b/WebCore/bindings/scripts/CodeGeneratorGObject.pm new file mode 100644 index 0000000..2a38eff --- /dev/null +++ b/WebCore/bindings/scripts/CodeGeneratorGObject.pm @@ -0,0 +1,1086 @@ +# Copyright (C) 2008 Luke Kenneth Casson Leighton <lkcl@lkcl.net> +# Copyright (C) 2008 Martin Soto <soto@freedesktop.org> +# Copyright (C) 2008 Alp Toker <alp@atoker.com> +# Copyright (C) 2009 Adam Dingle <adam@yorba.org> +# Copyright (C) 2009 Jim Nelson <jim@yorba.org> +# Copyright (C) 2009, 2010 Igalia S.L. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library 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 +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; see the file COPYING.LIB. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +package CodeGeneratorGObject; + +# Global Variables +my %implIncludes = (); +my %hdrIncludes = (); + +my $className = ""; + +# Default constructor +sub new { + my $object = shift; + my $reference = { }; + + $codeGenerator = shift; + $outputDir = shift; + mkdir $outputDir; + + bless($reference, $object); +} + +sub finish { +} + +my $licenceTemplate = << "EOF"; +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +EOF + +sub GenerateModule { +} + +sub GetParentClassName { + my $dataNode = shift; + + return "WebKitDOMObject" if @{$dataNode->parents} eq 0; + return "WebKitDOM" . $codeGenerator->StripModule($dataNode->parents(0)); +} + +# From String::CamelCase 0.01 +sub camelize +{ + my $s = shift; + join('', map{ ucfirst $_ } split(/(?<=[A-Za-z])_(?=[A-Za-z])|\b/, $s)); +} + +sub decamelize +{ + my $s = shift; + $s =~ s{([^a-zA-Z]?)([A-Z]*)([A-Z])([a-z]?)}{ + my $fc = pos($s)==0; + my ($p0,$p1,$p2,$p3) = ($1,lc$2,lc$3,$4); + my $t = $p0 || $fc ? $p0 : '_'; + $t .= $p3 ? $p1 ? "${p1}_$p2$p3" : "$p2$p3" : "$p1$p2"; + $t; + }ge; + $s; +} + +sub ClassNameToGObjectType { + my $className = shift; + my $CLASS_NAME = uc(decamelize($className)); + # Fixup: with our prefix being 'WebKitDOM' decamelize can't get + # WebKitDOMCSS right, so we have to fix it manually (and there + # might be more like this in the future) + $CLASS_NAME =~ s/DOMCSS/DOM_CSS/; + return $CLASS_NAME; +} + +sub GetParentGObjType { + my $dataNode = shift; + + return "WEBKIT_TYPE_DOM_OBJECT" if @{$dataNode->parents} eq 0; + return "WEBKIT_TYPE_DOM_" . ClassNameToGObjectType($codeGenerator->StripModule($dataNode->parents(0))); +} + +sub GetClassName { + my $name = $codeGenerator->StripModule(shift); + + return "WebKitDOM$name"; +} + +sub GetCoreObject { + my ($interfaceName, $name, $parameter) = @_; + + return "WebCore::${interfaceName}* $name = WebKit::core($parameter);"; +} + +sub SkipAttribute { + my $attribute = shift; + + if ($attribute->signature->extendedAttributes->{"CustomGetter"} || + $attribute->signature->extendedAttributes->{"CustomSetter"}) { + return 1; + } + + my $propType = $attribute->signature->type; + if ($propType eq "EventListener") { + return 1; + } + + if ($propType =~ /Constructor$/) { + return 1; + } + + return 0; +} + +# Name type used in the g_value_{set,get}_* functions +sub GetGValueTypeName { + my $type = shift; + + my %types = ("DOMString", "string", + "float", "float", + "double", "double", + "boolean", "boolean", + "char", "char", + "long", "long", + "short", "int", + "uchar", "uchar", + "unsigned", "uint", + "int", "int", + "unsigned int", "uint", + "unsigned long long", "uint64", + "unsigned long", "ulong", + "unsigned short", "ushort"); + + return $types{$type} ? $types{$type} : "object"; +} + +# Name type used in C declarations +sub GetGlibTypeName { + my $type = shift; + my $name = GetClassName($type); + + my %types = ("DOMString", "gchar* ", + "float", "gfloat", + "double", "gdouble", + "boolean", "gboolean", + "char", "gchar", + "long", "glong", + "short", "gshort", + "uchar", "guchar", + "unsigned", "guint", + "int", "gint", + "unsigned int", "guint", + "unsigned long", "gulong", + "unsigned long long", "guint64", + "unsigned short", "gushort", + "void", "void"); + + return $types{$type} ? $types{$type} : "$name* "; +} + +sub IsGDOMClassType { + my $type = shift; + + return 0 if $type eq "DOMString"; + return 0 if $type eq "float"; + return 0 if $type eq "double"; + return 0 if $type eq "boolean"; + return 0 if $type eq "char"; + return 0 if $type eq "long"; + return 0 if $type eq "short"; + return 0 if $type eq "uchar"; + return 0 if $type eq "unsigned"; + return 0 if $type eq "int"; + return 0 if $type eq "unsigned int"; + return 0 if $type eq "unsigned long"; + return 0 if $type eq "unsigned long long"; + return 0 if $type eq "unsigned short"; + return 0 if $type eq "void"; + + return 1; +} + +sub GenerateProperties { + my ($object, $interfaceName, $dataNode) = @_; + + my $clsCaps = substr(ClassNameToGObjectType($className), 12); + my $lowerCaseIfaceName = "webkit_dom_" . (decamelize($interfaceName)); + + # Properties + my $implContent = ""; + + # Properties + $implContent = << "EOF"; +enum { + PROP_0, +EOF + push(@cBodyPriv, $implContent); + + my @txtInstallProps = (); + my @txtSetProps = (); + my @txtGetProps = (); + + my $privFunction = GetCoreObject($interfaceName, "coreSelf", "self"); + + my $txtGetProp = << "EOF"; +static void ${lowerCaseIfaceName}_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) +{ + ${className}* self = WEBKIT_DOM_${clsCaps}(object); + $privFunction + + switch (prop_id) { +EOF + push(@txtGetProps, $txtGetProp); + + my $txtSetProps = << "EOF"; +static void ${lowerCaseIfaceName}_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) +{ + ${className} *self = WEBKIT_DOM_${clsCaps}(object); + $privFunction + + switch (prop_id) { +EOF + push(@txtSetProps, $txtSetProps); + + # Iterate over the interface attributes and generate a property for + # each one of them. + SKIPENUM: + foreach my $attribute (@{$dataNode->attributes}) { + if (SkipAttribute($attribute)) { + next SKIPENUM; + } + + my $camelPropName = $attribute->signature->name; + my $setPropNameFunction = $codeGenerator->WK_ucfirst($camelPropName); + my $getPropNameFunction = $codeGenerator->WK_lcfirst($camelPropName); + + my $propName = decamelize($camelPropName); + my $propNameCaps = uc($propName); + $propName =~ s/_/-/g; + my ${propEnum} = "PROP_${propNameCaps}"; + push(@cBodyPriv, " ${propEnum},\n"); + + my $propType = $attribute->signature->type; + my ${propGType} = decamelize($propType); + if ($propGType eq "event_target") { + $propGType = "event_target_node"; + } + my ${ucPropGType} = uc($propGType); + + my $gtype = GetGValueTypeName($propType); + my $gparamflag = "WEBKIT_PARAM_READABLE"; + my $writeable = $attribute->type !~ /^readonly/; + my $const = "read-only "; + if ($writeable && $custom) { + $const = "read-only (due to custom functions needed in webkitdom)"; + next SKIPENUM; + } + if ($writeable && !$custom) { + $gparamflag = "WEBKIT_PARAM_READWRITE"; + $const = "read-write "; + } + + my $type = GetGlibTypeName($propType); + $nick = decamelize("${interfaceName}_${propName}"); + $long = "${const} ${type} ${interfaceName}.${propName}"; + + my $convertFunction = ""; + + if ($writeable && ($gtype eq "boolean" || $gtype eq "float" || $gtype eq "double" || + $gtype eq "uint64" || $gtype eq "ulong" || $gtype eq "long" || + $gtype eq "uint" || $gtype eq "ushort" || $gtype eq "uchar" || + $gtype eq "char" || $gtype eq "string")) { + + push(@txtSetProps, " case ${propEnum}:\n {\n"); + push(@txtSetProps, " WebCore::ExceptionCode ec = 0;\n") if @{$attribute->setterExceptions}; + + if ($gtype eq "string") { + $convertFunction = "WebCore::String::fromUTF8"; + } elsif ($attribute->signature->extendedAttributes->{"ConvertFromString"}) { + $convertFunction = "WebCore::String::number"; + } + + push(@txtSetProps, " coreSelf->set${setPropNameFunction}(${convertFunction}(g_value_get_$gtype(value))"); + push(@txtSetProps, ", ec") if @{$attribute->setterExceptions}; + push(@txtSetProps, ");\n"); + + push(@txtSetProps, " break;\n }\n"); + } + + push(@txtGetProps, " case ${propEnum}:\n {\n"); + + my $exception = ""; + if (@{$attribute->getterExceptions}) { + $exception = "ec"; + push(@txtGetProps, " WebCore::ExceptionCode ec = 0;\n"); + } + + my $postConvertFunction = ""; + my $done = 0; + if ($gtype eq "string") { + push(@txtGetProps, " g_value_take_string(value, convertToUTF8String(coreSelf->${getPropNameFunction}(${exception})));\n"); + $done = 1; + } elsif ($gtype eq "object") { + + $txtGetProp = << "EOF"; + RefPtr<WebCore::${propType}> ptr = coreSelf->${getPropNameFunction}(${exception}); + g_value_set_object(value, WebKit::kit(ptr.get())); +EOF + push(@txtGetProps, $txtGetProp); + + $done = 1; + } + + if($attribute->signature->extendedAttributes->{"ConvertFromString"}) { + # TODO: Add other conversion functions for different types. Current + # IDLs only list longs. + if($gtype eq "long") { + $convertFunction = ""; + $postConvertFunction = ".toInt()"; + } else { + die "Can't convert to type ${gtype}."; + } + } + + # FIXME: get rid of this glitch? + my $_gtype = $gtype; + if ($gtype eq "ushort") { + $_gtype = "uint"; + } + + if (!$done) { + push(@txtGetProps, " g_value_set_$_gtype(value, ${convertFunction}coreSelf->${getPropNameFunction}(${exception})${postConvertFunction});\n"); + } + + push(@txtGetProps, " break;\n }\n"); + +my %param_spec_options = ("int", "G_MININT, /* min */\nG_MAXINT, /* max */\n0, /* default */", + "boolean", "FALSE, /* default */", + "float", "G_MINFLOAT, /* min */\nG_MAXFLOAT, /* max */\n0.0, /* default */", + "double", "G_MINDOUBLE, /* min */\nG_MAXDOUBLE, /* max */\n0.0, /* default */", + "uint64", "0, /* min */\nG_MAXUINT64, /* min */\n0, /* default */", + "long", "G_MINLONG, /* min */\nG_MAXLONG, /* max */\n0, /* default */", + "ulong", "0, /* min */\nG_MAXULONG, /* max */\n0, /* default */", + "uint", "0, /* min */\nG_MAXUINT, /* max */\n0, /* default */", + "ushort", "0, /* min */\nG_MAXUINT16, /* max */\n0, /* default */", + "uchar", "G_MININT8, /* min */\nG_MAXINT8, /* max */\n0, /* default */", + "char", "0, /* min */\nG_MAXUINT8, /* max */\n0, /* default */", + "string", "\"\", /* default */", + "object", "WEBKIT_TYPE_DOM_${ucPropGType}, /* gobject type */"); + + my $txtInstallProp = << "EOF"; + g_object_class_install_property(gobjectClass, + ${propEnum}, + g_param_spec_${_gtype}("${propName}", /* name */ + "$nick", /* short description */ + "$long", /* longer - could do with some extra doc stuff here */ + $param_spec_options{$gtype} + ${gparamflag})); +EOF + push(@txtInstallProps, $txtInstallProp); + $txtInstallProp = "/* TODO! $gtype */\n"; + } + + push(@cBodyPriv, "};\n\n"); + + $txtGetProp = << "EOF"; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} +EOF + push(@txtGetProps, $txtGetProp); + + $txtSetProps = << "EOF"; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} +EOF + push(@txtSetProps, $txtSetProps); + + # TODO: work out if it's appropriate to split this into many different + # signals e.g. "click" etc. + my $txtInstallSignals = ""; + + $implContent = << "EOF"; + +static void ${lowerCaseIfaceName}_finalize(GObject* object) +{ + WebKitDOMObject* dom_object = WEBKIT_DOM_OBJECT(object); + + if (dom_object->coreObject != NULL) { + WebCore::${interfaceName}* coreObject = static_cast<WebCore::${interfaceName} *>(dom_object->coreObject); + + WebKit::DOMObjectCache::forget(coreObject); + coreObject->deref(); + + dom_object->coreObject = NULL; + } + + G_OBJECT_CLASS(${lowerCaseIfaceName}_parent_class)->finalize(object); +} + +@txtSetProps + +@txtGetProps + +static void ${lowerCaseIfaceName}_class_init(${className}Class* requestClass) +{ + GObjectClass *gobjectClass = G_OBJECT_CLASS(requestClass); + gobjectClass->finalize = ${lowerCaseIfaceName}_finalize; + gobjectClass->set_property = ${lowerCaseIfaceName}_set_property; + gobjectClass->get_property = ${lowerCaseIfaceName}_get_property; + +@txtInstallProps + +$txtInstallSignals +} + +static void ${lowerCaseIfaceName}_init(${className}* request) +{ +} + +EOF + push(@cBodyPriv, $implContent); +} + +sub GenerateHeader { + my ($object, $interfaceName, $parentClassName) = @_; + + my $implContent = ""; + + # Add the default header template + @hPrefix = split("\r", $licenceTemplate); + push(@hPrefix, "\n"); + + #Header guard + my $guard = $className . "_h"; + + @hPrefixGuard = << "EOF"; +#ifndef $guard +#define $guard + +EOF + + $implContent = << "EOF"; +G_BEGIN_DECLS +EOF + + push(@hBodyPre, $implContent); + + my $clsCaps = uc(decamelize($interfaceName)); + my $lowerCaseIfaceName = "webkit_dom_" . (decamelize($interfaceName)); + + $implContent = << "EOF"; + +#define WEBKIT_TYPE_DOM_${clsCaps} (${lowerCaseIfaceName}_get_type()) +#define WEBKIT_DOM_${clsCaps}(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_DOM_${clsCaps}, ${className})) +#define WEBKIT_DOM_${clsCaps}_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_DOM_${clsCaps}, ${className}Class) +#define WEBKIT_DOM_IS_${clsCaps}(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_DOM_${clsCaps})) +#define WEBKIT_DOM_IS_${clsCaps}_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_DOM_${clsCaps})) +#define WEBKIT_DOM_${clsCaps}_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_DOM_${clsCaps}, ${className}Class)) + +struct _${className} { + ${parentClassName} parent_instance; +}; + +struct _${className}Class { + ${parentClassName}Class parent_class; +}; + +WEBKIT_API GType +${lowerCaseIfaceName}_get_type (void); + +EOF + + push(@hBody, $implContent); +} + +sub getIncludeHeader { + my $type = shift; + my $name = GetClassName($type); + + return "" if $type eq "int"; + return "" if $type eq "long"; + return "" if $type eq "short"; + return "" if $type eq "char"; + return "" if $type eq "float"; + return "" if $type eq "double"; + return "" if $type eq "unsigned"; + return "" if $type eq "unsigned int"; + return "" if $type eq "unsigned long"; + return "" if $type eq "unsigned long long"; + return "" if $type eq "unsigned short"; + return "" if $type eq "DOMTimeStamp"; + return "" if $type eq "EventListener"; + return "" if $type eq "unsigned char"; + return "" if $type eq "DOMString"; + return "" if $type eq "float"; + return "" if $type eq "boolean"; + return "" if $type eq "void"; + + return "$name.h"; +} + +sub addIncludeInBody { + my $type = shift; + + my $header = getIncludeHeader($type); + if ($header eq "") { + return; + } + + if (IsGDOMClassType($type)) { + $implIncludes{"webkit/$header"} = 1; + } else { + $implIncludes{$header} = 1 + } +} + +sub GenerateFunction { + my ($object, $interfaceName, $function, $prefix) = @_; + + my $functionSigName = $function->signature->name; + my $functionSigType = $function->signature->type; + my $functionName = "webkit_dom_" . decamelize($interfaceName) . "_" . $prefix . decamelize($functionSigName); + my $returnType = GetGlibTypeName($functionSigType); + my $returnValueIsGDOMType = IsGDOMClassType($functionSigType); + + my $functionSig = "$className *self"; + + my $callImplParams = ""; + + # skip some custom functions for now + my $isCustomFunction = $function->signature->extendedAttributes->{"Custom"} || + $function->signature->extendedAttributes->{"CustomArgumentHandling"}; + + foreach my $param (@{$function->parameters}) { + my $paramIDLType = $param->type; + if ($paramIDLType eq "Event") { + push(@hBody, "\n/* TODO: event function ${functionName} */\n\n"); + push(@cBody, "\n/* TODO: event function ${functionName} */\n\n"); + return; + } + addIncludeInBody($paramIDLType); + my $paramType = GetGlibTypeName($paramIDLType); + my $paramName = decamelize($param->name); + + $functionSig .= ", $paramType $paramName"; + + my $paramIsGDOMType = IsGDOMClassType($paramIDLType); + if ($paramIsGDOMType) { + if ($paramIDLType ne "DOMObject") { + $implIncludes{"webkit/WebKitDOM${paramIDLType}Private.h"} = 1; + } + } + if ($paramIsGDOMType || ($paramIDLType eq "DOMString")) { + $paramName = "_g_" . $paramName; + } + if ($callImplParams) { + $callImplParams .= ", $paramName"; + } else { + $callImplParams = "$paramName"; + } + } + + if ($functionSigType eq "Event") { + push(@hBody, "\n/* TODO: event function ${functionName} */\n\n"); + push(@cBody, "\n/* TODO: event function ${functionName} */\n\n"); + return; + } + + if ($returnType ne "void" && $returnValueIsGDOMType) { + if ($functionSigType ne "EventTarget") { + $implIncludes{"webkit/WebKitDOM${functionSigType}Private.h"} = 1; + $implIncludes{"webkit/WebKitDOM${functionSigType}.h"} = 1; + } + + $implIncludes{"${functionSigType}.h"} = 1; + } + + # skip custom functions for now + # but skip from here to allow some headers to be created + # for a successful compile. + if ($isCustomFunction && + $functionName ne "webkit_dom_node_remove_child" && + $functionName ne "webkit_dom_node_insert_before" && + $functionName ne "webkit_dom_node_replace_child" && + $functionName ne "webkit_dom_node_append_child") { + push(@hBody, "\n/* TODO: custom function ${functionName} */\n\n"); + push(@cBody, "\n/* TODO: custom function ${functionName} */\n\n"); + return; + } + + if(@{$function->raisesExceptions}) { + $functionSig .= ", GError **error"; + } + + push(@hBody, "WEBKIT_API $returnType\n$functionName ($functionSig);\n\n"); + push(@cBody, "$returnType\n$functionName ($functionSig)\n{\n"); + + if ($returnType ne "void") { + # TODO: return proper default result + push(@cBody, " g_return_val_if_fail (self, 0);\n"); + } else { + push(@cBody, " g_return_if_fail (self);\n"); + } + + # The WebKit::core implementations check for NULL already; no need to + # duplicate effort. + push(@cBody, " WebCore::${interfaceName} * item = WebKit::core(self);\n"); + + foreach my $param (@{$function->parameters}) { + my $paramName = decamelize($param->name); + my $paramIDLType = $param->type; + my $paramTypeIsPrimitive = $codeGenerator->IsPrimitiveType($paramIDLType); + my $paramIsGDOMType = IsGDOMClassType($paramIDLType); + if (!$paramTypeIsPrimitive) { + if ($returnType ne "void") { + # TODO: return proper default result + push(@cBody, " g_return_val_if_fail ($paramName, 0);\n"); + } else { + push(@cBody, " g_return_if_fail ($paramName);\n"); + } + } + } + + $returnParamName = ""; + foreach my $param (@{$function->parameters}) { + my $paramIDLType = $param->type; + my $paramName = decamelize($param->name); + + my $paramIsGDOMType = IsGDOMClassType($paramIDLType); + if ($paramIDLType eq "DOMString") { + push(@cBody, " WebCore::String _g_${paramName} = WebCore::String::fromUTF8($paramName);\n"); + } + if ($paramIsGDOMType) { + push(@cBody, " WebCore::${paramIDLType} * _g_${paramName} = WebKit::core($paramName);\n"); + if ($returnType ne "void") { + # TODO: return proper default result + push(@cBody, " g_return_val_if_fail (_g_${paramName}, 0);\n"); + } else { + push(@cBody, " g_return_if_fail (_g_${paramName});\n"); + } + } + $returnParamName = "_g_".$paramName if $param->extendedAttributes->{"Return"}; + } + + my $assign = ""; + my $assignPre = ""; + my $assignPost = ""; + + if ($returnType ne "void" && !$isCustomFunction) { + if ($returnValueIsGDOMType) { + $assign = "PassRefPtr<WebCore::${functionSigType}> g_res = "; + $assignPre = "WTF::getPtr("; + $assignPost = ")"; + } else { + $assign = "${returnType} res = "; + } + } + my $exceptions = ""; + if (@{$function->raisesExceptions}) { + push(@cBody, " WebCore::ExceptionCode ec = 0;\n"); + if (${callImplParams} ne "") { + $exceptions = ", ec"; + } else { + $exceptions = "ec"; + } + } + + # We need to special-case these Node methods because their C++ signature is different + # from what we'd expect given their IDL description; see Node.h. + if ($functionName eq "webkit_dom_node_append_child" || + $functionName eq "webkit_dom_node_insert_before" || + $functionName eq "webkit_dom_node_replace_child" || + $functionName eq "webkit_dom_node_remove_child") { + my $customNodeAppendChild = << "EOF"; + bool ok = item->${functionSigName}(${callImplParams}${exceptions}); + if (ok) + { + ${returnType} res = static_cast<${returnType}>(WebKit::kit($returnParamName)); + return res; + } +EOF + push(@cBody, $customNodeAppendChild); + + if(@{$function->raisesExceptions}) { + my $exceptionHandling = << "EOF"; + + WebCore::ExceptionCodeDescription ecdesc; + WebCore::getExceptionCodeDescription(ec, ecdesc); + g_set_error_literal(error, g_quark_from_string("WEBKIT_DOM"), ecdesc.code, ecdesc.name); +EOF + push(@cBody, $exceptionHandling); + } + push(@cBody, "return NULL;"); + push(@cBody, "}\n\n"); + return; + } elsif ($functionSigType eq "DOMString") { + push(@cBody, " ${assign}convertToUTF8String(item->${functionSigName}(${callImplParams}${exceptions}));\n" ); + } else { + push(@cBody, " ${assign}${assignPre}item->${functionSigName}(${callImplParams}${exceptions}${assignPost});\n" ); + + if(@{$function->raisesExceptions}) { + my $exceptionHandling = << "EOF"; + if(ec) { + WebCore::ExceptionCodeDescription ecdesc; + WebCore::getExceptionCodeDescription(ec, ecdesc); + g_set_error_literal(error, g_quark_from_string("WEBKIT_DOM"), ecdesc.code, ecdesc.name); + } +EOF + push(@cBody, $exceptionHandling); + } + } + + if ($returnType ne "void" && !$isCustomFunction) { + if ($functionSigType ne "DOMObject") { + if ($returnValueIsGDOMType) { + push(@cBody, " ${returnType} res = static_cast<${returnType}>(WebKit::kit(g_res.get()));\n"); + } + } + if ($functionSigType eq "DOMObject") { + push(@cBody, " return NULL; /* TODO: return canvas object */\n"); + } else { + push(@cBody, " return res;\n"); + } + } + push(@cBody, "\n}\n\n"); +} + +sub ClassHasFunction { + my ($class, $name) = @_; + + foreach my $function (@{$class->functions}) { + if ($function->signature->name eq $name) { + return 1; + } + } + + return 0; +} + +sub GenerateFunctions { + my ($object, $interfaceName, $dataNode) = @_; + + foreach my $function (@{$dataNode->functions}) { + $object->GenerateFunction($interfaceName, $function, ""); + } + + TOP: + foreach my $attribute (@{$dataNode->attributes}) { + if (SkipAttribute($attribute)) { + next TOP; + } + + if ($attribute->signature->name eq "type" + # This will conflict with the get_type() function we define to return a GType + # according to GObject conventions. Skip this for now. + || $attribute->signature->name eq "URL" # TODO: handle this + || $attribute->signature->extendedAttributes->{"ConvertFromString"} # TODO: handle this + ) { + next TOP; + } + + my $attrNameUpper = $codeGenerator->WK_ucfirst($attribute->signature->name); + my $getname = "get${attrNameUpper}"; + my $setname = "set${attrNameUpper}"; + if (ClassHasFunction($dataNode, $getname) || ClassHasFunction($dataNode, $setname)) { + # Very occasionally an IDL file defines getter/setter functions for one of its + # attributes; in this case we don't need to autogenerate the getter/setter. + next TOP; + } + + # Generate an attribute getter. For an attribute "foo", this is a function named + # "get_foo" which calls a DOM class method named foo(). + my $function = new domFunction(); + $function->signature($attribute->signature); + $function->raisesExceptions($attribute->getterExceptions); + $object->GenerateFunction($interfaceName, $function, "get_"); + + if ($attribute->type =~ /^readonly/ || + $attribute->signature->extendedAttributes->{"Replaceable"} # can't handle this yet + ) { + next TOP; + } + + # Generate an attribute setter. For an attribute, "foo", this is a function named + # "set_foo" which calls a DOM class method named setFoo(). + $function = new domFunction(); + + $function->signature(new domSignature()); + $function->signature->name($setname); + $function->signature->type("void"); + $function->signature->extendedAttributes($attribute->signature->extendedAttributes); + + my $param = new domSignature(); + $param->name("value"); + $param->type($attribute->signature->type); + my %attributes = (); + $param->extendedAttributes(attributes); + my $arrayRef = $function->parameters; + push(@$arrayRef, $param); + + $function->raisesExceptions($attribute->setterExceptions); + + $object->GenerateFunction($interfaceName, $function, ""); + } +} + +sub GenerateCFile { + my ($object, $interfaceName, $parentClassName, $parentGObjType, $dataNode) = @_; + my $implContent = ""; + + my $clsCaps = uc(decamelize($interfaceName)); + my $lowerCaseIfaceName = "webkit_dom_" . decamelize($interfaceName); + + $implContent = << "EOF"; +G_DEFINE_TYPE(${className}, ${lowerCaseIfaceName}, ${parentGObjType}) + +namespace WebKit { + +${className}* wrap${interfaceName}(WebCore::${interfaceName}* coreObject) +{ + g_return_val_if_fail(coreObject != 0, 0); + + ${className}* wrapper = WEBKIT_DOM_${clsCaps}(g_object_new(WEBKIT_TYPE_DOM_${clsCaps}, NULL)); + g_return_val_if_fail(wrapper != 0, 0); + + /* We call ref() rather than using a C++ smart pointer because we can't store a C++ object + * in a C-allocated GObject structure. See the finalize() code for the + * matching deref(). + */ + + coreObject->ref(); + WEBKIT_DOM_OBJECT(wrapper)->coreObject = coreObject; + + return wrapper; +} + +WebCore::${interfaceName}* core(${className}* request) +{ + g_return_val_if_fail(request != 0, 0); + + WebCore::${interfaceName}* coreObject = static_cast<WebCore::${interfaceName}*>(WEBKIT_DOM_OBJECT(request)->coreObject); + g_return_val_if_fail(coreObject != 0, 0); + + return coreObject; +} + +} // namespace WebKit +EOF + + push(@cBodyPriv, $implContent); + $object->GenerateProperties($interfaceName, $dataNode); + $object->GenerateFunctions($interfaceName, $dataNode); +} + +sub GenerateEndHeader { + my ($object) = @_; + + #Header guard + my $guard = $className . "_h"; + + push(@hBody, "G_END_DECLS\n\n"); + push(@hBody, "#endif /* $guard */\n"); +} + +sub GeneratePrivateHeader { + my $object = shift; + my $dataNode = shift; + + my $interfaceName = $dataNode->name; + my $filename = "$outputDir/" . $className . "Private.h"; + my $guard = uc(decamelize($className)) . "_PRIVATE_H"; + my $parentClassName = GetParentClassName($dataNode); + my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"}; + my $hasRealParent = @{$dataNode->parents} > 0; + my $hasParent = $hasLegacyParent || $hasRealParent; + + open(PRIVHEADER, ">$filename") or die "Couldn't open file $filename for writing"; + + print PRIVHEADER split("\r", $licenceTemplate); + print PRIVHEADER "\n"; + + my $text = << "EOF"; +#ifndef $guard +#define $guard + +#include <glib-object.h> +#include <webkit/${parentClassName}.h> +#include "${interfaceName}.h" +EOF + + print PRIVHEADER $text; + + print PRIVHEADER map { "#include \"$_\"\n" } sort keys(%hdrPropIncludes); + print PRIVHEADER "\n" if keys(%hdrPropIncludes); + + $text = << "EOF"; +namespace WebKit { + ${className} * + wrap${interfaceName}(WebCore::${interfaceName} *coreObject); + + WebCore::${interfaceName} * + core(${className} *request); + +EOF + + print PRIVHEADER $text; + + if ($className ne "WebKitDOMNode") { + $text = << "EOF"; + gpointer + kit(WebCore::${interfaceName}* node); + +EOF + print PRIVHEADER $text; + } + + $text = << "EOF"; +} // namespace WebKit + +#endif /* ${guard} */ +EOF + print PRIVHEADER $text; + + close(PRIVHEADER); +} + +sub UsesManualToJSImplementation { + my $type = shift; + + return 1 if $type eq "Node" or $type eq "Document" or $type eq "HTMLCollection" or + $type eq "SVGPathSeg" or $type eq "StyleSheet" or $type eq "CSSRule" or $type eq "CSSValue" or + $type eq "Event" or $type eq "Element" or $type eq "Text"; + return 0; +} + +sub Generate { + my ($object, $dataNode) = @_; + + my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"}; + my $hasRealParent = @{$dataNode->parents} > 0; + my $hasParent = $hasLegacyParent || $hasRealParent; + my $parentClassName = GetParentClassName($dataNode); + my $parentGObjType = GetParentGObjType($dataNode); + my $interfaceName = $dataNode->name; + + # Add the default impl header template + @cPrefix = split("\r", $licenceTemplate); + push(@cPrefix, "\n"); + + $implIncludes{"webkitmarshal.h"} = 1; + $implIncludes{"webkitprivate.h"} = 1; + $implIncludes{"WebKitDOMBinding.h"} = 1; + $implIncludes{"gobject/ConvertToUTF8String.h"} = 1; + $implIncludes{"webkit/$className.h"} = 1; + $implIncludes{"webkit/${className}Private.h"} = 1; + $implIncludes{"${interfaceName}.h"} = 1; + $implIncludes{"ExceptionCode.h"} = 1; + + $hdrIncludes{"webkit/${parentClassName}.h"} = 1; + + if ($className ne "WebKitDOMNode") { + my $converter = << "EOF"; +namespace WebKit { + +gpointer kit(WebCore::$interfaceName* obj) +{ + g_return_val_if_fail(obj != 0, 0); + + if (gpointer ret = DOMObjectCache::get(obj)) + return ret; + + return DOMObjectCache::put(obj, WebKit::wrap${interfaceName}(obj)); +} + +} // namespace WebKit // + +EOF + push(@cBody, $converter); + } + + $object->GenerateHeader($interfaceName, $parentClassName); + $object->GenerateCFile($interfaceName, $parentClassName, $parentGObjType, $dataNode); + $object->GenerateEndHeader(); + $object->GeneratePrivateHeader($dataNode); +} + +# Internal helper +sub WriteData { + my ($object, $name) = @_; + + # Write public header. + my $hdrFName = "$outputDir/" . $name . ".h"; + open(HEADER, ">$hdrFName") or die "Couldn't open file $hdrFName"; + + print HEADER @hPrefix; + print HEADER @hPrefixGuard; + print HEADER "#include \"webkit/webkitdomdefines.h\"\n"; + print HEADER "#include <glib-object.h>\n"; + print HEADER "#include <webkit/webkitdefines.h>\n"; + print HEADER map { "#include \"$_\"\n" } sort keys(%hdrIncludes); + print HEADER "\n" if keys(%hdrIncludes); + print HEADER "\n"; + print HEADER @hBodyPre; + print HEADER @hBody; + + close(HEADER); + + # Write the implementation sources + my $implFileName = "$outputDir/" . $name . ".cpp"; + open(IMPL, ">$implFileName") or die "Couldn't open file $implFileName"; + + print IMPL @cPrefix; + print IMPL "#include <glib-object.h>\n"; + print IMPL "#include \"config.h\"\n\n"; + print IMPL "#include <wtf/GetPtr.h>\n"; + print IMPL "#include <wtf/RefPtr.h>\n"; + print IMPL map { "#include \"$_\"\n" } sort keys(%implIncludes); + print IMPL "\n" if keys(%implIncludes); + print IMPL @cBody; + + print IMPL "\n"; + print IMPL @cBodyPriv; + + close(IMPL); + + %implIncludes = (); + %hdrIncludes = (); + @hPrefix = (); + @hBody = (); + + @cPrefix = (); + @cBody = (); + @cBodyPriv = (); +} + +sub GenerateInterface { + my ($object, $dataNode, $defines) = @_; + my $name = $dataNode->name; + + # Set up some global variables + $className = GetClassName($dataNode->name); + $object->Generate($dataNode); + + # Write changes + my $fname = "WebKitDOM_" . $name; + $fname =~ s/_//g; + $object->WriteData($fname); +} diff --git a/WebCore/bindings/scripts/CodeGeneratorJS.pm b/WebCore/bindings/scripts/CodeGeneratorJS.pm index 94fc2b8..919e321 100644 --- a/WebCore/bindings/scripts/CodeGeneratorJS.pm +++ b/WebCore/bindings/scripts/CodeGeneratorJS.pm @@ -17,7 +17,7 @@ # Library General Public License for more details. # # You should have received a copy of the GNU Library General Public License -# aint with this library; see the file COPYING.LIB. If not, write to +# along with this library; see the file COPYING.LIB. If not, write to # the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, # Boston, MA 02110-1301, USA. @@ -32,6 +32,7 @@ my $writeDependencies = 0; my @headerContentHeader = (); my @headerContent = (); my %headerIncludes = (); +my %headerTrailingIncludes = (); my @implContentHeader = (); my @implContent = (); @@ -143,6 +144,7 @@ sub GetVisibleClassName my $className = shift; return "DOMException" if $className eq "DOMCoreException"; + return "FormData" if $className eq "DOMFormData"; return $className; } @@ -212,12 +214,32 @@ sub AddIncludesForSVGAnimatedType } } +sub IsScriptProfileType +{ + my $type = shift; + return 1 if ($type eq "ScriptProfile" or $type eq "ScriptProfileNode"); + return 0; +} + +sub AddTypedefForScriptProfileType +{ + my $type = shift; + (my $jscType = $type) =~ s/Script//; + + push(@headerContent, "typedef JSC::$jscType $type;\n\n"); +} + sub AddClassForwardIfNeeded { my $implClassName = shift; # SVGAnimatedLength/Number/etc. are typedefs to SVGAnimatedTemplate, so don't use class forwards for them! - push(@headerContent, "class $implClassName;\n\n") unless $codeGenerator->IsSVGAnimatedType($implClassName); + unless ($codeGenerator->IsSVGAnimatedType($implClassName) or IsScriptProfileType($implClassName)) { + push(@headerContent, "class $implClassName;\n\n"); + # ScriptProfile and ScriptProfileNode are typedefs to JSC::Profile and JSC::ProfileNode. + } elsif (IsScriptProfileType($implClassName)) { + AddTypedefForScriptProfileType($implClassName); + } } sub IsSVGTypeNeedingContextParameter @@ -517,6 +539,7 @@ sub GenerateHeader # Get correct pass/store types respecting PODType flag my $podType = $dataNode->extendedAttributes->{"PODType"}; my $implType = $podType ? "JSSVGPODTypeWrapper<$podType> " : $implClassName; + $headerIncludes{"$podType.h"} = 1 if $podType and $podType ne "float"; $headerIncludes{"JSSVGPODTypeWrapper.h"} = 1 if $podType; @@ -551,7 +574,9 @@ sub GenerateHeader # Prototype push(@headerContent, " static JSC::JSObject* createPrototype(JSC::ExecState*, JSC::JSGlobalObject*);\n") unless ($dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"}); - $implIncludes{"${className}Custom.h"} = 1 if $dataNode->extendedAttributes->{"CustomHeader"} || $dataNode->extendedAttributes->{"CustomPutFunction"} || $dataNode->extendedAttributes->{"DelegatingPutFunction"}; + $headerTrailingIncludes{"${className}Custom.h"} = 1 if $dataNode->extendedAttributes->{"CustomHeader"}; + + $implIncludes{"${className}Custom.h"} = 1 if !$dataNode->extendedAttributes->{"CustomHeader"} && ($dataNode->extendedAttributes->{"CustomPutFunction"} || $dataNode->extendedAttributes->{"DelegatingPutFunction"}); my $hasGetter = $numAttributes > 0 || !($dataNode->extendedAttributes->{"OmitConstructor"} @@ -743,7 +768,7 @@ sub GenerateHeader # Index getter if ($dataNode->extendedAttributes->{"HasIndexGetter"}) { - push(@headerContent, " static JSC::JSValue indexGetter(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);\n"); + push(@headerContent, " static JSC::JSValue indexGetter(JSC::ExecState*, JSC::JSValue, unsigned);\n"); } if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) { push(@headerContent, " JSC::JSValue getByIndex(JSC::ExecState*, unsigned index);\n"); @@ -758,7 +783,7 @@ sub GenerateHeader if ($dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}) { push(@headerContent, "private:\n"); push(@headerContent, " static bool canGetItemsForName(JSC::ExecState*, $implClassName*, const JSC::Identifier&);\n"); - push(@headerContent, " static JSC::JSValue nameGetter(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);\n"); + push(@headerContent, " static JSC::JSValue nameGetter(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&);\n"); } push(@headerContent, "};\n\n"); @@ -859,7 +884,7 @@ sub GenerateHeader push(@headerContent,"// Attributes\n\n"); foreach my $attribute (@{$dataNode->attributes}) { my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : ""); - push(@headerContent, "JSC::JSValue ${getter}(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);\n"); + push(@headerContent, "JSC::JSValue ${getter}(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&);\n"); unless ($attribute->type =~ /readonly/) { my $setter = "setJS" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : ""); push(@headerContent, "void ${setter}(JSC::ExecState*, JSC::JSObject*, JSC::JSValue);\n"); @@ -868,7 +893,7 @@ sub GenerateHeader if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) { my $getter = "js" . $interfaceName . "Constructor"; - push(@headerContent, "JSC::JSValue ${getter}(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);\n"); + push(@headerContent, "JSC::JSValue ${getter}(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&);\n"); } } @@ -876,7 +901,7 @@ sub GenerateHeader push(@headerContent,"// Constants\n\n"); foreach my $constant (@{$dataNode->constants}) { my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name); - push(@headerContent, "JSC::JSValue ${getter}(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);\n"); + push(@headerContent, "JSC::JSValue ${getter}(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&);\n"); } } @@ -1286,9 +1311,9 @@ sub GenerateImplementation push(@implContent, "#if ${conditionalString}\n"); } - push(@implContent, "JSValue ${getFunctionName}(ExecState* exec, const Identifier&, const PropertySlot& slot)\n"); + push(@implContent, "JSValue ${getFunctionName}(ExecState* exec, JSValue slotBase, const Identifier&)\n"); push(@implContent, "{\n"); - push(@implContent, " ${className}* castedThis = static_cast<$className*>(asObject(slot.slotBase()));\n"); + push(@implContent, " ${className}* castedThis = static_cast<$className*>(asObject(slotBase));\n"); my $implClassNameForValueConversion = ""; if (!$podType and ($codeGenerator->IsSVGAnimatedType($implClassName) or $attribute->type !~ /^readonly/)) { @@ -1402,9 +1427,9 @@ sub GenerateImplementation if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) { my $constructorFunctionName = "js" . $interfaceName . "Constructor"; - push(@implContent, "JSValue ${constructorFunctionName}(ExecState* exec, const Identifier&, const PropertySlot& slot)\n"); + push(@implContent, "JSValue ${constructorFunctionName}(ExecState* exec, JSValue slotBase, const Identifier&)\n"); push(@implContent, "{\n"); - push(@implContent, " ${className}* domObject = static_cast<$className*>(asObject(slot.slotBase()));\n"); + push(@implContent, " ${className}* domObject = static_cast<$className*>(asObject(slotBase));\n"); push(@implContent, " return ${className}::getConstructor(exec, domObject->globalObject());\n"); push(@implContent, "}\n"); } @@ -1461,6 +1486,12 @@ sub GenerateImplementation my $putFunctionName = "setJS" . $interfaceName . $codeGenerator->WK_ucfirst($name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : ""); my $implSetterFunctionName = $codeGenerator->WK_ucfirst($name); + my $conditional = $attribute->signature->extendedAttributes->{"Conditional"}; + if ($conditional) { + $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; + push(@implContent, "#if ${conditionalString}\n"); + } + push(@implContent, "void ${putFunctionName}(ExecState* exec, JSObject* thisObject, JSValue value)\n"); push(@implContent, "{\n"); @@ -1478,12 +1509,28 @@ sub GenerateImplementation } elsif ($type eq "EventListener") { $implIncludes{"JSEventListener.h"} = 1; push(@implContent, " UNUSED_PARAM(exec);\n"); + my $windowEventListener = $attribute->signature->extendedAttributes->{"WindowEventListener"}; + if ($windowEventListener) { + push(@implContent, " ${className}* castedThis = static_cast<${className}*>(thisObject);\n"); + push(@implContent, " JSDOMGlobalObject* globalObject = castedThis->globalObject();\n"); + } push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(static_cast<$className*>(thisObject)->impl());\n"); - push(@implContent, " imp->set$implSetterFunctionName(createJSAttributeEventListener(exec, value, thisObject));\n"); + if ($interfaceName eq "WorkerContext" and $name eq "onerror") { + $implIncludes{"JSWorkerContextErrorHandler.h"} = 1; + push(@implContent, " imp->set$implSetterFunctionName(createJSWorkerContextErrorHandler(exec, value, thisObject));\n"); + } else { + if ($windowEventListener) { + push(@implContent, " imp->set$implSetterFunctionName(createJSAttributeEventListener(exec, value, globalObject));\n"); + } else { + push(@implContent, " imp->set$implSetterFunctionName(createJSAttributeEventListener(exec, value, thisObject));\n"); + } + } } elsif ($attribute->signature->type =~ /Constructor$/) { my $constructorType = $attribute->signature->type; $constructorType =~ s/Constructor$//; - $implIncludes{"JS" . $constructorType . ".h"} = 1; + if ($constructorType ne "DOMObject") { + $implIncludes{"JS" . $constructorType . ".h"} = 1; + } push(@implContent, " // Shadowing a built-in constructor\n"); push(@implContent, " static_cast<$className*>(thisObject)->putDirect(Identifier(exec, \"$name\"), value);\n"); } elsif ($attribute->signature->extendedAttributes->{"Replaceable"}) { @@ -1522,7 +1569,13 @@ sub GenerateImplementation } } - push(@implContent, "}\n\n"); + push(@implContent, "}\n"); + + if ($conditional) { + push(@implContent, "#endif\n"); + } + + push(@implContent, "\n"); } } } @@ -1701,7 +1754,7 @@ sub GenerateImplementation my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name); # FIXME: this casts into int to match our previous behavior which turned 0xFFFFFFFF in -1 for NodeFilter.SHOW_ALL - push(@implContent, "JSValue ${getter}(ExecState* exec, const Identifier&, const PropertySlot&)\n"); + push(@implContent, "JSValue ${getter}(ExecState* exec, JSValue, const Identifier&)\n"); push(@implContent, "{\n"); push(@implContent, " return jsNumber(exec, static_cast<int>(" . $constant->value . "));\n"); push(@implContent, "}\n\n"); @@ -1709,14 +1762,14 @@ sub GenerateImplementation } if ($dataNode->extendedAttributes->{"HasIndexGetter"}) { - push(@implContent, "\nJSValue ${className}::indexGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)\n"); + push(@implContent, "\nJSValue ${className}::indexGetter(ExecState* exec, JSValue slotBase, unsigned index)\n"); push(@implContent, "{\n"); - push(@implContent, " ${className}* thisObj = static_cast<$className*>(asObject(slot.slotBase()));\n"); + push(@implContent, " ${className}* thisObj = static_cast<$className*>(asObject(slotBase));\n"); if (IndexGetterReturnsStrings($implClassName)) { $implIncludes{"KURL.h"} = 1; - push(@implContent, " return jsStringOrNull(exec, thisObj->impl()->item(slot.index()));\n"); + push(@implContent, " return jsStringOrNull(exec, thisObj->impl()->item(index));\n"); } else { - push(@implContent, " return toJS(exec, thisObj->globalObject(), static_cast<$implClassName*>(thisObj->impl())->item(slot.index()));\n"); + push(@implContent, " return toJS(exec, thisObj->globalObject(), static_cast<$implClassName*>(thisObj->impl())->item(index));\n"); } push(@implContent, "}\n"); if ($interfaceName eq "HTMLCollection" or $interfaceName eq "HTMLAllCollection") { @@ -1832,7 +1885,8 @@ sub GetNativeTypeFromSignature my %nativeType = ( "CompareHow" => "Range::CompareHow", - "DOMString" => "const UString&", + "DOMString" => "const String&", + "DOMObject" => "ScriptValue", "NodeFilter" => "RefPtr<NodeFilter>", "SVGAngle" => "SVGAngle", "SVGLength" => "SVGLength", @@ -1883,7 +1937,11 @@ sub JSValueToNative if ($type eq "DOMString") { return "valueToStringWithNullCheck(exec, $value)" if $signature->extendedAttributes->{"ConvertNullToNullString"}; return "valueToStringWithUndefinedOrNullCheck(exec, $value)" if $signature->extendedAttributes->{"ConvertUndefinedOrNullToNullString"}; - return "$value.toString(exec)"; + return "ustringToString($value.toString(exec))"; + } + + if ($type eq "DOMObject") { + return "$value"; } if ($type eq "SerializedScriptValue" or $type eq "any") { @@ -1985,7 +2043,11 @@ sub NativeToJSValue } if ($type eq "DOMObject") { - $implIncludes{"JSCanvasRenderingContext2D.h"} = 1; + if ($implClassName eq "Document") { + $implIncludes{"JSCanvasRenderingContext2D.h"} = 1; + } else { + return "$value.jsValue();"; + } } elsif ($type =~ /SVGPathSeg/) { $implIncludes{"JS$type.h"} = 1; $joinedName = $type; @@ -2123,6 +2185,7 @@ tableSizeLoop: $i = 0; foreach my $key (@{$keys}) { my $conditional; + my $targetType; if ($conditionals) { $conditional = $conditionals->{$key}; @@ -2131,7 +2194,13 @@ tableSizeLoop: my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; push(@implContent, "#if ${conditionalString}\n"); } - push(@implContent, " { \"$key\", @$specials[$i], (intptr_t)@$value1[$i], (intptr_t)@$value2[$i] },\n"); + + if ("@$specials[$i]" =~ m/Function/) { + $targetType = "static_cast<NativeFunction>"; + } else { + $targetType = "static_cast<PropertySlot::GetValueFunc>"; + } + push(@implContent, " { \"$key\", @$specials[$i], (intptr_t)" . $targetType . "(@$value1[$i]), (intptr_t)@$value2[$i] },\n"); if ($conditional) { push(@implContent, "#endif\n"); } @@ -2246,12 +2315,23 @@ sub WriteData } print $HEADER @headerContent; + + @includes = (); + foreach my $include (keys %headerTrailingIncludes) { + $include = "\"$include\"" unless $include =~ /^["<]/; # " + push @includes, $include; + } + foreach my $include (sort @includes) { + print $HEADER "#include $include\n"; + } + close($HEADER); undef($HEADER); @headerContentHeader = (); @headerContent = (); %headerIncludes = (); + %headerTrailingIncludes = (); } if (defined($DEPS)) { diff --git a/WebCore/bindings/scripts/CodeGeneratorObjC.pm b/WebCore/bindings/scripts/CodeGeneratorObjC.pm index dcb22a7..3c5fe45 100644 --- a/WebCore/bindings/scripts/CodeGeneratorObjC.pm +++ b/WebCore/bindings/scripts/CodeGeneratorObjC.pm @@ -17,7 +17,7 @@ # Library General Public License for more details. # # You should have received a copy of the GNU Library General Public License -# aint with this library; see the file COPYING.LIB. If not, write to +# along with this library; see the file COPYING.LIB. If not, write to # the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, # Boston, MA 02110-1301, USA. # @@ -222,7 +222,13 @@ sub ReadPublicInterfaces %publicInterfaces = (); my $fileName = "WebCore/bindings/objc/PublicDOMInterfaces.h"; - open FILE, "-|", "/usr/bin/gcc", "-E", "-P", "-x", "objective-c", + my $gccLocation = ""; + if (($Config::Config{'osname'}) =~ /solaris/i) { + $gccLocation = "/usr/sfw/bin/gcc"; + } else { + $gccLocation = "/usr/bin/gcc"; + } + open FILE, "-|", $gccLocation, "-E", "-P", "-x", "objective-c", (map { "-D$_" } split(/ +/, $defines)), "-DOBJC_CODE_GENERATION", $fileName or die "Could not open $fileName"; my @documentContent = <FILE>; close FILE; diff --git a/WebCore/bindings/scripts/CodeGeneratorV8.pm b/WebCore/bindings/scripts/CodeGeneratorV8.pm index ee51ec3..1c5f398 100644 --- a/WebCore/bindings/scripts/CodeGeneratorV8.pm +++ b/WebCore/bindings/scripts/CodeGeneratorV8.pm @@ -18,7 +18,7 @@ # Library General Public License for more details. # # You should have received a copy of the GNU Library General Public License -# aint with this library; see the file COPYING.LIB. If not, write to +# along with this library; see the file COPYING.LIB. If not, write to # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # @@ -84,11 +84,6 @@ sub finish $object->WriteData(); } -sub leftShift($$) { - my ($value, $distance) = @_; - return (($value << $distance) & 0xFFFFFFFF); -} - # Workaround for V8 bindings difference where RGBColor is not a POD type. sub IsPodType { @@ -126,13 +121,6 @@ sub GenerateModule $module = $dataNode->module; } -sub GetLegacyHeaderIncludes -{ - my $legacyParent = shift; - - die "Don't know what headers to include for module $module"; -} - sub AvoidInclusionOfType { my $type = shift; @@ -142,14 +130,6 @@ sub AvoidInclusionOfType return 0; } -sub UsesManualToJSImplementation -{ - my $type = shift; - - return 1 if $type eq "SVGPathSeg"; - return 0; -} - sub AddIncludesForType { my $type = $codeGenerator->StripModule(shift); @@ -203,14 +183,6 @@ sub AddIncludesForSVGAnimatedType $implIncludes{"SVGAnimatedTemplate.h"} = 1; } -sub AddClassForwardIfNeeded -{ - my $implClassName = shift; - - # SVGAnimatedLength/Number/etc.. are typedefs to SVGAnimtatedTemplate, so don't use class forwards for them! - push(@headerContent, "class $implClassName;\n\n") unless $codeGenerator->IsSVGAnimatedType($implClassName); -} - # If the node has a [Conditional=XXX] attribute, returns an "ENABLE(XXX)" string for use in an #if. sub GenerateConditionalString { @@ -223,6 +195,23 @@ sub GenerateConditionalString } } +sub LinkOverloadedFunctions +{ + my $dataNode = shift; + + # Identifies overloaded functions and for each function adds an array with + # links to its respective overloads (including itself). + my %nameToFunctionsMap = (); + foreach my $function (@{$dataNode->functions}) { + my $name = $function->signature->name; + $nameToFunctionsMap{$name} = [] if !exists $nameToFunctionsMap{$name}; + push(@{$nameToFunctionsMap{$name}}, $function); + $function->{overloads} = $nameToFunctionsMap{$name}; + $function->{overloadIndex} = @{$nameToFunctionsMap{$name}}; + } + +} + sub GenerateHeader { my $object = shift; @@ -243,19 +232,26 @@ sub GenerateHeader @headerContent = split("\r", $headerTemplate); push(@headerContent, "\n#if ${conditionalString}\n\n") if $conditionalString; - push(@headerContent, "\n#ifndef $className" . "_H"); - push(@headerContent, "\n#define $className" . "_H\n\n"); + push(@headerContent, "\n#ifndef $className" . "_h"); + push(@headerContent, "\n#define $className" . "_h\n\n"); # Get correct pass/store types respecting PODType flag my $podType = $dataNode->extendedAttributes->{"PODType"}; - push(@headerContent, "#include \"$podType.h\"\n") if $podType and ($podType ne "double" and $podType ne "float" and $podType ne "RGBA32"); + my %headerInclues = (); + $headerIncludes{"$podType.h"} = 1 if $podType and ($podType ne "double" and $podType ne "float" and $podType ne "RGBA32"); + $headerIncludes{"StringHash.h"} = 1; + $headerIncludes{"WrapperTypeInfo.h"} = 1; + my $headerClassInclude = GetHeaderClassInclude($implClassName); + $headerIncludes{$headerClassInclude} = 1 if $headerClassInclude ne ""; + + foreach my $headerInclude (sort keys(%headerIncludes)) { + push(@headerContent, "#include \"${headerInclude}\"\n"); + } push(@headerContent, "#include <v8.h>\n"); push(@headerContent, "#include <wtf/HashMap.h>\n"); - push(@headerContent, "#include \"StringHash.h\"\n"); - push(@headerContent, "#include \"V8Index.h\"\n"); - push(@headerContent, GetHeaderClassInclude($implClassName)); + push(@headerContent, "\nnamespace WebCore {\n"); if ($podType) { push(@headerContent, "\ntemplate<typename PODType> class V8SVGPODTypeWrapper;\n"); @@ -269,17 +265,22 @@ sub GenerateHeader my $forceNewObjectParameter = IsDOMNodeType($interfaceName) ? ", bool forceNewObject = false" : ""; push(@headerContent, <<END); - public: - static bool HasInstance(v8::Handle<v8::Value> value); - static v8::Persistent<v8::FunctionTemplate> GetRawTemplate(); - static v8::Persistent<v8::FunctionTemplate> GetTemplate(); - static ${nativeType}* toNative(v8::Handle<v8::Object>); - static v8::Handle<v8::Object> wrap(${nativeType}*${forceNewObjectParameter}); +public: + static bool HasInstance(v8::Handle<v8::Value> value); + static v8::Persistent<v8::FunctionTemplate> GetRawTemplate(); + static v8::Persistent<v8::FunctionTemplate> GetTemplate(); + static ${nativeType}* toNative(v8::Handle<v8::Object>); + static v8::Handle<v8::Object> wrap(${nativeType}*${forceNewObjectParameter}); + static void derefObject(void*); + static WrapperTypeInfo info; END + if (IsActiveDomType($implClassName)) { + push(@headerContent, " static ActiveDOMObject* toActiveDOMObject(v8::Handle<v8::Object>);\n"); + } if ($implClassName eq "DOMWindow") { - push(@headerContent, <<END); - static v8::Persistent<v8::ObjectTemplate> GetShadowObjectTemplate(); + push(@headerContent, <<END); + static v8::Persistent<v8::ObjectTemplate> GetShadowObjectTemplate(); END } @@ -288,11 +289,12 @@ END my $name = $function->signature->name; my $attrExt = $function->signature->extendedAttributes; - # FIXME: We should only be generating callback declarations for functions labeled [Custom] or [V8Custom], - # but we can't do that due to some mislabeled functions in the idl's (https://bugs.webkit.org/show_bug.cgi?id=33066). - push(@headerContent, <<END); - static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments&); + if ($attrExt->{"Custom"} || $attrExt->{"V8Custom"}) { + push(@headerContent, <<END); + static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments&); END + } + if ($attrExt->{"EnabledAtRuntime"}) { push(@enabledAtRuntime, $function); } @@ -300,7 +302,7 @@ END if ($dataNode->extendedAttributes->{"CustomConstructor"} || $dataNode->extendedAttributes->{"CanBeConstructed"}) { push(@headerContent, <<END); - static v8::Handle<v8::Value> constructorCallback(const v8::Arguments& args); + static v8::Handle<v8::Value> constructorCallback(const v8::Arguments& args); END } @@ -310,13 +312,13 @@ END if ($attrExt->{"V8CustomGetter"} || $attrExt->{"CustomGetter"} || $attrExt->{"V8Custom"} || $attrExt->{"Custom"}) { push(@headerContent, <<END); - static v8::Handle<v8::Value> ${name}AccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info); + static v8::Handle<v8::Value> ${name}AccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info); END } if ($attrExt->{"V8CustomSetter"} || $attrExt->{"CustomSetter"} || $attrExt->{"V8Custom"} || $attrExt->{"Custom"}) { push(@headerContent, <<END); - static void ${name}AccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info); + static void ${name}AccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info); END } if ($attrExt->{"EnabledAtRuntime"}) { @@ -330,24 +332,24 @@ END if ($dataNode->extendedAttributes->{"CheckDomainSecurity"}) { push(@headerContent, <<END); - static bool namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType, v8::Local<v8::Value> data); - static bool indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType, v8::Local<v8::Value> data); + static bool namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType, v8::Local<v8::Value> data); + static bool indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType, v8::Local<v8::Value> data); END } push(@headerContent, <<END); }; - v8::Handle<v8::Value> toV8(${nativeType}*${forceNewObjectParameter}); +v8::Handle<v8::Value> toV8(${nativeType}*${forceNewObjectParameter}); END if (IsRefPtrType($implClassName)) { push(@headerContent, <<END); - v8::Handle<v8::Value> toV8(PassRefPtr<${nativeType} >${forceNewObjectParameter}); +v8::Handle<v8::Value> toV8(PassRefPtr<${nativeType} >${forceNewObjectParameter}); END } push(@headerContent, "}\n\n"); - push(@headerContent, "#endif // $className" . "_H\n"); + push(@headerContent, "#endif // $className" . "_h\n"); push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString; } @@ -356,33 +358,25 @@ sub GetInternalFields { my $dataNode = shift; my $name = $dataNode->name; - - # FIXME: I am hideous and hard-coded. Make me beautiful. - return ("cacheIndex", "implementationIndex") if ($name eq "Document") || ($name eq "SVGDocument"); - return ("cacheIndex", "implementationIndex", "markerIndex", "shadowIndex") if $name eq "HTMLDocument"; - return ("cacheIndex") if IsNodeSubType($dataNode); - return ("cacheIndex") if $name eq "EventSource"; - return ("cacheIndex") if $name eq "XMLHttpRequest"; - return ("cacheIndex") if $name eq "XMLHttpRequestUpload"; - return ("cacheIndex") if $name eq "MessagePort"; - return ("port1Index", "port2Index") if ($name eq "MessageChannel"); - return ("cacheIndex") if $name eq "AbstractWorker"; - return ("abstractWorkerCacheIndex", "cacheIndex") if $name eq "Worker"; - return ("abstractWorkerCacheIndex", "cacheIndex") if $name eq "WorkerContext"; - return ("abstractWorkerCacheIndex", "workerContextCacheIndex", "cacheIndex") if $name eq "DedicatedWorkerContext"; - return ("abstractWorkerCacheIndex", "cacheIndex") if $name eq "SharedWorker"; - return ("abstractWorkerCacheIndex", "workerContextCacheIndex", "cacheIndex") if $name eq "SharedWorkerContext"; - return ("cacheIndex") if $name eq "Notification"; - return ("cacheIndex") if $name eq "IDBRequest"; - return ("cacheIndex") if $name eq "SVGElementInstance"; - return ("consoleIndex", "historyIndex", "locationbarIndex", "menubarIndex", "navigatorIndex", "personalbarIndex", - "screenIndex", "scrollbarsIndex", "selectionIndex", "statusbarIndex", "toolbarIndex", "locationIndex", - "domSelectionIndex", "cacheIndex", "enteredIsolatedWorldIndex") if $name eq "DOMWindow"; - return ("cacheIndex") if $name eq "DOMApplicationCache"; - return ("cacheIndex") if $name eq "WebSocket"; - return ("ownerNodeIndex") if ($name eq "StyleSheet") || ($name eq "CSSStyleSheet"); - return ("ownerNodeIndex") if ($name eq "NamedNodeMap"); - return (); + + my @customInternalFields = (); + + # We can't ask whether a parent type has a given extendedAttribute, so special-case Node, AbstractWorker and WorkerContext to include all sub-types. + # FIXME: SVGElementInstance should probably have the EventTarget extended attribute, but doesn't. + if ($dataNode->extendedAttributes->{"EventTarget"} || IsNodeSubType($dataNode) || IsSubType($dataNode, "AbstractWorker") || IsSubType($dataNode, "WorkerContext") + || $name eq "SVGElementInstance") { + push(@customInternalFields, "eventListenerCacheIndex"); + } + + if (IsSubType($dataNode, "Document")) { + push(@customInternalFields, "implementationIndex"); + if ($name eq "HTMLDocument") { + push(@customInternalFields, ("markerIndex", "shadowIndex")); + } + } elsif ($name eq "DOMWindow") { + push(@customInternalFields, "enteredIsolatedWorldIndex"); + } + return @customInternalFields; } sub GetHeaderClassInclude @@ -392,8 +386,8 @@ sub GetHeaderClassInclude $className =~ s/Abs|Rel//; } return "" if (AvoidInclusionOfType($className)); - return "#include \"SVGAnimatedTemplate.h\"\n" if ($codeGenerator->IsSVGAnimatedType($className)); - return "#include \"${className}.h\"\n"; + return "SVGAnimatedTemplate.h" if ($codeGenerator->IsSVGAnimatedType($className)); + return "${className}.h"; } sub GenerateHeaderCustomInternalFieldIndices @@ -403,12 +397,12 @@ sub GenerateHeaderCustomInternalFieldIndices my $customFieldCounter = 0; foreach my $customInternalField (@customInternalFields) { push(@headerContent, <<END); - static const int ${customInternalField} = v8DefaultWrapperInternalFieldCount + ${customFieldCounter}; + static const int ${customInternalField} = v8DefaultWrapperInternalFieldCount + ${customFieldCounter}; END $customFieldCounter++; } push(@headerContent, <<END); - static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + ${customFieldCounter}; + static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + ${customFieldCounter}; END } @@ -439,45 +433,45 @@ sub GenerateHeaderNamedAndIndexedPropertyAccessors $hasCustomDeleterr = 0; $hasEnumerator = 0; } - if ($interfaceName eq "HTMLSelectElement") { + if ($interfaceName eq "HTMLSelectElement" || $interfaceName eq "HTMLAppletElement" || $interfaceName eq "HTMLEmbedElement" || $interfaceName eq "HTMLObjectElement") { $hasCustomNamedGetter = 1; } my $isIndexerSpecialCase = exists $indexerSpecialCases{$interfaceName}; if ($hasCustomIndexedGetter || $isIndexerSpecialCase) { push(@headerContent, <<END); - static v8::Handle<v8::Value> indexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info); + static v8::Handle<v8::Value> indexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info); END } if ($isIndexerSpecialCase || $hasCustomIndexedSetter) { push(@headerContent, <<END); - static v8::Handle<v8::Value> indexedPropertySetter(uint32_t index, v8::Local<v8::Value> value, const v8::AccessorInfo& info); + static v8::Handle<v8::Value> indexedPropertySetter(uint32_t index, v8::Local<v8::Value> value, const v8::AccessorInfo& info); END } if ($hasCustomDeleters) { push(@headerContent, <<END); - static v8::Handle<v8::Boolean> indexedPropertyDeleter(uint32_t index, const v8::AccessorInfo& info); + static v8::Handle<v8::Boolean> indexedPropertyDeleter(uint32_t index, const v8::AccessorInfo& info); END } if ($hasCustomNamedGetter) { push(@headerContent, <<END); - static v8::Handle<v8::Value> namedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info); + static v8::Handle<v8::Value> namedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info); END } if ($hasCustomNamedSetter) { push(@headerContent, <<END); - static v8::Handle<v8::Value> namedPropertySetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info); + static v8::Handle<v8::Value> namedPropertySetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info); END } if ($hasCustomDeleters || $interfaceName eq "HTMLDocument") { push(@headerContent, <<END); - static v8::Handle<v8::Boolean> namedPropertyDeleter(v8::Local<v8::String> name, const v8::AccessorInfo& info); + static v8::Handle<v8::Boolean> namedPropertyDeleter(v8::Local<v8::String> name, const v8::AccessorInfo& info); END } if ($hasCustomEnumerator) { push(@headerContent, <<END); - static v8::Handle<v8::Array> namedPropertyEnumerator(const v8::AccessorInfo& info); + static v8::Handle<v8::Array> namedPropertyEnumerator(const v8::AccessorInfo& info); END } } @@ -487,16 +481,16 @@ sub GenerateHeaderCustomCall my $dataNode = shift; if ($dataNode->extendedAttributes->{"CustomCall"}) { - push(@headerContent, " static v8::Handle<v8::Value> callAsFunctionCallback(const v8::Arguments&);\n"); + push(@headerContent, " static v8::Handle<v8::Value> callAsFunctionCallback(const v8::Arguments&);\n"); } if ($dataNode->name eq "Event") { - push(@headerContent, " static v8::Handle<v8::Value> dataTransferAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n"); - push(@headerContent, " static void valueAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info);\n"); + push(@headerContent, " static v8::Handle<v8::Value> dataTransferAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n"); + push(@headerContent, " static void valueAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info);\n"); } if ($dataNode->name eq "Location") { - push(@headerContent, " static v8::Handle<v8::Value> assignAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n"); - push(@headerContent, " static v8::Handle<v8::Value> reloadAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n"); - push(@headerContent, " static v8::Handle<v8::Value> replaceAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n"); + push(@headerContent, " static v8::Handle<v8::Value> assignAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n"); + push(@headerContent, " static v8::Handle<v8::Value> reloadAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n"); + push(@headerContent, " static v8::Handle<v8::Value> replaceAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info);\n"); } } @@ -531,19 +525,12 @@ sub IsNodeSubType return IsSubType($dataNode, "Node"); } -sub IsEventSubType -{ - my $dataNode = shift; - return IsSubType($dataNode, "Event"); -} - sub GenerateDomainSafeFunctionGetter { my $function = shift; - my $dataNode = shift; my $implClassName = shift; - my $className = "V8" . $dataNode->name; + my $className = "V8" . $implClassName; my $funcName = $function->signature->name; my $signature = "v8::Signature::New(" . $className . "::GetRawTemplate())"; @@ -551,29 +538,26 @@ sub GenerateDomainSafeFunctionGetter $signature = "v8::Local<v8::Signature>()"; } - my $newTemplateString = GenerateNewFunctionTemplate($function, $dataNode, $signature); + my $newTemplateString = GenerateNewFunctionTemplate($function, $implClassName, $signature); push(@implContentDecls, <<END); - static v8::Handle<v8::Value> ${funcName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { +static v8::Handle<v8::Value> ${funcName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ INC_STATS(\"DOM.$implClassName.$funcName._get\"); - static v8::Persistent<v8::FunctionTemplate> private_template = - v8::Persistent<v8::FunctionTemplate>::New($newTemplateString); + static v8::Persistent<v8::FunctionTemplate> privateTemplate = v8::Persistent<v8::FunctionTemplate>::New($newTemplateString); v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(${className}::GetTemplate(), info.This()); if (holder.IsEmpty()) { - // can only reach here by 'object.__proto__.func', and it should passed - // domain security check already - return private_template->GetFunction(); + // can only reach here by 'object.__proto__.func', and it should passed + // domain security check already + return privateTemplate->GetFunction(); } ${implClassName}* imp = ${className}::toNative(holder); if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false)) { - static v8::Persistent<v8::FunctionTemplate> shared_template = - v8::Persistent<v8::FunctionTemplate>::New($newTemplateString); - return shared_template->GetFunction(); - - } else { - return private_template->GetFunction(); + static v8::Persistent<v8::FunctionTemplate> sharedTemplate = v8::Persistent<v8::FunctionTemplate>::New($newTemplateString); + return sharedTemplate->GetFunction(); } - } + return privateTemplate->GetFunction(); +} END } @@ -581,24 +565,24 @@ END sub GenerateConstructorGetter { my $implClassName = shift; - my $classIndex = shift; push(@implContentDecls, <<END); - static v8::Handle<v8::Value> ${implClassName}ConstructorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { +static v8::Handle<v8::Value> ${implClassName}ConstructorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ INC_STATS(\"DOM.$implClassName.constructors._get\"); v8::Handle<v8::Value> data = info.Data(); - ASSERT(data->IsNumber()); - V8ClassIndex::V8WrapperType type = V8ClassIndex::FromInt(data->Int32Value()); + ASSERT(data->IsExternal() || data->IsNumber()); + WrapperTypeInfo* type = WrapperTypeInfo::unwrap(data); END - if ($classIndex eq "DOMWINDOW") { + if ($implClassName eq "DOMWindow") { push(@implContentDecls, <<END); // Get the proxy corresponding to the DOMWindow if possible to // make sure that the constructor function is constructed in the // context of the DOMWindow and not in the context of the caller. return V8DOMWrapper::getConstructor(type, V8DOMWindow::toNative(info.Holder())); END - } elsif ($classIndex eq "DEDICATEDWORKERCONTEXT" or $classIndex eq "WORKERCONTEXT" or $classIndex eq "SHAREDWORKERCONTEXT") { + } elsif ($implClassName eq "DedicatedWorkerContext" or $implClassName eq "WorkerContext" or $implClassName eq "SharedWorkerContext") { push(@implContentDecls, <<END); return V8DOMWrapper::getConstructor(type, V8WorkerContext::toNative(info.Holder())); END @@ -607,8 +591,7 @@ END } push(@implContentDecls, <<END); - - } +} END } @@ -631,7 +614,6 @@ sub GenerateNormalAttrGetter my $isPodType = IsPodType($implClassName); my $skipContext = 0; - if ($isPodType) { $implClassName = GetNativeType($implClassName); $implIncludes{"V8SVGPODTypeWrapper.h"} = 1; @@ -658,34 +640,36 @@ sub GenerateNormalAttrGetter # Getter push(@implContentDecls, <<END); - static v8::Handle<v8::Value> ${attrName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { +static v8::Handle<v8::Value> ${attrName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ INC_STATS(\"DOM.$implClassName.$attrName._get\"); END if ($isPodType) { push(@implContentDecls, <<END); - V8SVGPODTypeWrapper<$implClassName>* imp_wrapper = V8SVGPODTypeWrapper<$implClassName>::toNative(info.Holder()); - $implClassName imp_instance = *imp_wrapper; + V8SVGPODTypeWrapper<$implClassName>* impWrapper = V8SVGPODTypeWrapper<$implClassName>::toNative(info.Holder()); + $implClassName impInstance = *impWrapper; END if ($getterStringUsesImp) { push(@implContentDecls, <<END); - $implClassName* imp = &imp_instance; + $implClassName* imp = &impInstance; END } } elsif ($attrExt->{"v8OnProto"} || $attrExt->{"V8DisallowShadowing"}) { - if ($interfaceName eq "DOMWindow") { - push(@implContentDecls, <<END); + if ($interfaceName eq "DOMWindow") { + push(@implContentDecls, <<END); v8::Handle<v8::Object> holder = info.Holder(); END - } else { - # perform lookup first - push(@implContentDecls, <<END); + } else { + # perform lookup first + push(@implContentDecls, <<END); v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8${interfaceName}::GetTemplate(), info.This()); - if (holder.IsEmpty()) return v8::Handle<v8::Value>(); + if (holder.IsEmpty()) + return v8::Handle<v8::Value>(); END - } - push(@implContentDecls, <<END); + } + push(@implContentDecls, <<END); ${implClassName}* imp = V8${implClassName}::toNative(holder); END } else { @@ -696,7 +680,7 @@ END my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName); $implIncludes{"${namespace}.h"} = 1; push(@implContentDecls, " return getElementStringAttr(info, ${namespace}::${contentAttributeName}Attr);\n"); - push(@implContentDecls, " }\n\n"); + push(@implContentDecls, "}\n\n"); return; # Skip the rest of the function! } @@ -707,9 +691,9 @@ END # Generate security checks if necessary if ($attribute->signature->extendedAttributes->{"CheckNodeSecurity"}) { - push(@implContentDecls, " if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->$attrName())) return v8::Handle<v8::Value>();\n\n"); + push(@implContentDecls, " if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->$attrName()))\n return v8::Handle<v8::Value>();\n\n"); } elsif ($attribute->signature->extendedAttributes->{"CheckFrameSecurity"}) { - push(@implContentDecls, " if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->contentDocument())) return v8::Handle<v8::Value>();\n\n"); + push(@implContentDecls, " if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->contentDocument()))\n return v8::Handle<v8::Value>();\n\n"); } my $useExceptions = 1 if @{$attribute->getterExceptions} and !($isPodType); @@ -751,7 +735,7 @@ END $getterString .= ".toInt()"; } } else { - $getterString = "imp_instance"; + $getterString = "impInstance"; } my $result; @@ -768,7 +752,7 @@ END my $implClassIsAnimatedType = $codeGenerator->IsSVGAnimatedType($implClassName); if (not $implClassIsAnimatedType and $codeGenerator->IsPodTypeWithWriteableProperties($attrType) and not defined $attribute->signature->extendedAttributes->{"Immutable"}) { if (IsPodType($implClassName)) { - my $wrapper = "V8SVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName>::create($getterString, imp_wrapper)"; + my $wrapper = "V8SVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName>::create($getterString, impWrapper)"; push(@implContentDecls, " RefPtr<V8SVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName> > wrapper = $wrapper;\n"); } else { my $wrapper = "V8SVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName>::create(imp, &${implClassName}::$getter, &${implClassName}::$setter)"; @@ -790,7 +774,7 @@ END } else { if ($attribute->signature->type eq "EventListener" && $dataNode->name eq "DOMWindow") { push(@implContentDecls, " if (!imp->document())\n"); - push(@implContentDecls, " return v8::Handle<v8::Value>();\n"); + push(@implContentDecls, " return v8::Handle<v8::Value>();\n"); } if ($useExceptions) { @@ -803,6 +787,32 @@ END # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary $result = $getterString; } + + # Special case for readonly or Replaceable attributes (with a few exceptions). This attempts to ensure that JS wrappers don't get + # garbage-collected prematurely when their lifetime is strongly tied to their owner. We accomplish this by inserting a reference to + # the newly created wrapper into an internal field of the holder object. + if (!IsNodeSubType($dataNode) && $attrName ne "self" && (IsWrapperType($returnType) && ($attribute->type =~ /^readonly/ || $attribute->signature->extendedAttributes->{"Replaceable"}) + && $returnType ne "EventTarget" && $returnType ne "SerializedScriptValue" && $returnType ne "DOMWindow" + && $returnType !~ /SVG/ && $returnType !~ /HTML/ && !IsDOMNodeType($returnType))) { + AddIncludesForType($returnType); + my $domMapFunction = GetDomMapFunction(0, $returnType); + # Check for a wrapper in the wrapper cache. If there is one, we know that a hidden reference has already + # been created. If we don't find a wrapper, we create both a wrapper and a hidden reference. + push(@implContentDecls, " RefPtr<$returnType> result = ${getterString};\n"); + push(@implContentDecls, " v8::Handle<v8::Value> wrapper = result.get() ? ${domMapFunction}.get(result.get()) : v8::Handle<v8::Value>();\n"); + push(@implContentDecls, " if (wrapper.IsEmpty()) {\n"); + push(@implContentDecls, " wrapper = toV8(result.get());\n"); + push(@implContentDecls, " if (!wrapper.IsEmpty())\n"); + if ($dataNode->name eq "DOMWindow") { + push(@implContentDecls, " V8DOMWrapper::setHiddenWindowReference(imp->frame(), wrapper);\n"); + } else { + push(@implContentDecls, " V8DOMWrapper::setHiddenReference(info.Holder(), wrapper);\n"); + } + push(@implContentDecls, " }\n"); + push(@implContentDecls, " return wrapper;\n"); + push(@implContentDecls, "}\n\n"); + return; + } } if (IsSVGTypeNeedingContextParameter($attrType) && !$skipContext) { @@ -824,27 +834,9 @@ END push(@implContentDecls, " " . ReturnNativeToJSValue($attribute->signature, $result, " ").";\n"); } - push(@implContentDecls, " }\n\n"); # end of getter -} - - -sub GenerateReplaceableAttrSetter -{ - my $implClassName = shift; - - push(@implContentDecls, - " static void ${attrName}AttrSetter(v8::Local<v8::String> name," . - " v8::Local<v8::Value> value, const v8::AccessorInfo& info) {\n"); - - push(@implContentDecls, " INC_STATS(\"DOM.$implClassName.$attrName._set\");\n"); - - push(@implContentDecls, " v8::Local<v8::String> ${attrName}_string = v8::String::New(\"${attrName}\");\n"); - push(@implContentDecls, " info.Holder()->Delete(${attrName}_string);\n"); - push(@implContentDecls, " info.This()->Set(${attrName}_string, value);\n"); - push(@implContentDecls, " }\n\n"); + push(@implContentDecls, "}\n\n"); # end of getter } - sub GenerateNormalAttrSetter { my $attribute = shift; @@ -854,10 +846,7 @@ sub GenerateNormalAttrSetter my $attrExt = $attribute->signature->extendedAttributes; - push(@implContentDecls, - " static void ${attrName}AttrSetter(v8::Local<v8::String> name," . - " v8::Local<v8::Value> value, const v8::AccessorInfo& info) {\n"); - + push(@implContentDecls, "static void ${attrName}AttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)\n{\n"); push(@implContentDecls, " INC_STATS(\"DOM.$implClassName.$attrName._set\");\n"); my $isPodType = IsPodType($implClassName); @@ -866,8 +855,8 @@ sub GenerateNormalAttrSetter $implClassName = GetNativeType($implClassName); $implIncludes{"V8SVGPODTypeWrapper.h"} = 1; push(@implContentDecls, " V8SVGPODTypeWrapper<$implClassName>* wrapper = V8SVGPODTypeWrapper<$implClassName>::toNative(info.Holder());\n"); - push(@implContentDecls, " $implClassName imp_instance = *wrapper;\n"); - push(@implContentDecls, " $implClassName* imp = &imp_instance;\n"); + push(@implContentDecls, " $implClassName impInstance = *wrapper;\n"); + push(@implContentDecls, " $implClassName* imp = &impInstance;\n"); } elsif ($attrExt->{"v8OnProto"}) { if ($interfaceName eq "DOMWindow") { @@ -878,7 +867,8 @@ END # perform lookup first push(@implContentDecls, <<END); v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8${interfaceName}::GetTemplate(), info.This()); - if (holder.IsEmpty()) return; + if (holder.IsEmpty()) + return; END } push(@implContentDecls, <<END); @@ -894,7 +884,7 @@ END my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName); $implIncludes{"${namespace}.h"} = 1; push(@implContentDecls, " setElementStringAttr(info, ${namespace}::${contentAttributeName}Attr, value);\n"); - push(@implContentDecls, " }\n\n"); + push(@implContentDecls, "}\n\n"); return; # Skip the rest of the function! } @@ -908,7 +898,7 @@ END if ($attribute->signature->type eq "EventListener") { if ($dataNode->name eq "DOMWindow") { push(@implContentDecls, " if (!imp->document())\n"); - push(@implContentDecls, " return;\n"); + push(@implContentDecls, " return;\n"); } } else { push(@implContentDecls, " $nativeType v = " . JSValueToNative($attribute->signature, "value") . ";\n"); @@ -947,8 +937,14 @@ END push(@implContentDecls, " imp->setAttribute(${namespace}::${contentAttributeName}Attr, $result"); } elsif ($attribute->signature->type eq "EventListener") { $implIncludes{"V8AbstractEventListener.h"} = 1; - push(@implContentDecls, " transferHiddenDependency(info.Holder(), imp->$attrName(), value, V8${interfaceName}::cacheIndex);\n"); - push(@implContentDecls, " imp->set$implSetterFunctionName(V8DOMWrapper::getEventListener(imp, value, true, ListenerFindOrCreate)"); + push(@implContentDecls, " transferHiddenDependency(info.Holder(), imp->$attrName(), value, V8${interfaceName}::eventListenerCacheIndex);\n"); + if ($interfaceName eq "WorkerContext" and $attribute->signature->name eq "onerror") { + $implIncludes{"V8EventListenerList.h"} = 1; + $implIncludes{"V8WorkerContextErrorHandler.h"} = 1; + push(@implContentDecls, " imp->set$implSetterFunctionName(V8EventListenerList::findOrCreateWrapper<V8WorkerContextErrorHandler>(value, true)"); + } else { + push(@implContentDecls, " imp->set$implSetterFunctionName(V8DOMWrapper::getEventListener(value, true, ListenerFindOrCreate)"); + } } else { push(@implContentDecls, " imp->set$implSetterFunctionName($result"); } @@ -971,21 +967,19 @@ END $currentObject = "wrapper"; } - push(@implContentDecls, " if (SVGElement* context = V8Proxy::svgContext($currentObject)) {\n"); + push(@implContentDecls, " if (SVGElement* context = V8Proxy::svgContext($currentObject))\n"); push(@implContentDecls, " context->svgAttributeChanged(imp->associatedAttributeName());\n"); - push(@implContentDecls, " }\n"); } push(@implContentDecls, " return;\n"); - push(@implContentDecls, " }\n\n"); # end of setter + push(@implContentDecls, "}\n\n"); # end of setter } sub GetFunctionTemplateCallbackName { $function = shift; - $dataNode = shift; + $interfaceName = shift; - my $interfaceName = $dataNode->name; my $name = $function->signature->name; if ($function->signature->extendedAttributes->{"Custom"} || @@ -1003,54 +997,167 @@ sub GetFunctionTemplateCallbackName sub GenerateNewFunctionTemplate { $function = shift; - $dataNode = shift; + $interfaceName = shift; $signature = shift; - my $callback = GetFunctionTemplateCallbackName($function, $dataNode); + my $callback = GetFunctionTemplateCallbackName($function, $interfaceName); return "v8::FunctionTemplate::New($callback, v8::Handle<v8::Value>(), $signature)"; } +sub GenerateEventListenerCallback +{ + my $implClassName = shift; + my $functionName = shift; + my $lookupType = ($functionName eq "add") ? "OrCreate" : "Only"; + my $passRefPtrHandling = ($functionName eq "add") ? "" : ".get()"; + my $hiddenDependencyAction = ($functionName eq "add") ? "create" : "remove"; + + push(@implContentDecls, <<END); +static v8::Handle<v8::Value> ${functionName}EventListenerCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.${implClassName}.${functionName}EventListener()"); + RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(args[1], false, ListenerFind${lookupType}); + if (listener) { + V8${implClassName}::toNative(args.Holder())->${functionName}EventListener(v8ValueToAtomicWebCoreString(args[0]), listener${passRefPtrHandling}, args[2]->BooleanValue()); + ${hiddenDependencyAction}HiddenDependency(args.Holder(), args[1], V8${implClassName}::eventListenerCacheIndex); + } + return v8::Undefined(); +} + +END +} + +sub GenerateParametersCheckExpression +{ + my $numParameters = shift; + my $function = shift; + + my @andExpression = (); + push(@andExpression, "args.Length() == $numParameters"); + my $parameterIndex = 0; + foreach $parameter (@{$function->parameters}) { + last if $parameterIndex >= $numParameters; + my $value = "args[$parameterIndex]"; + my $type = GetTypeFromSignature($parameter); + + # Only DOMString or wrapper types are checked. + # For DOMString, Null, Undefined and any Object are accepted too, as + # these are acceptable values for a DOMString argument (any Object can + # be converted to a string via .toString). + push(@andExpression, "(${value}->IsNull() || ${value}->IsUndefined() || ${value}->IsString() || ${value}->IsObject())") if $codeGenerator->IsStringType($type); + push(@andExpression, "(${value}->IsNull() || V8${type}::HasInstance($value))") if IsWrapperType($type); + + $parameterIndex++; + } + my $res = join(" && ", @andExpression); + $res = "($res)" if @andExpression > 1; + return $res; +} + +sub GenerateFunctionParametersCheck +{ + my $function = shift; + + my @orExpression = (); + my $numParameters = 0; + foreach $parameter (@{$function->parameters}) { + if ($parameter->extendedAttributes->{"Optional"}) { + push(@orExpression, GenerateParametersCheckExpression($numParameters, $function)); + } + $numParameters++; + } + push(@orExpression, GenerateParametersCheckExpression($numParameters, $function)); + return join(" || ", @orExpression); +} + +sub GenerateOverloadedFunctionCallback +{ + my $function = shift; + my $dataNode = shift; + my $implClassName = shift; + + # Generate code for choosing the correct overload to call. Overloads are + # chosen based on the total number of arguments passed and the type of + # values passed in non-primitive argument slots. When more than a single + # overload is applicable, precedence is given according to the order of + # declaration in the IDL. + + my $name = $function->signature->name; + push(@implContentDecls, <<END); +static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args) +{ + INC_STATS(\"DOM.$implClassName.$name\"); +END + + foreach my $overload (@{$function->{overloads}}) { + my $parametersCheck = GenerateFunctionParametersCheck($overload); + push(@implContentDecls, " if ($parametersCheck)\n"); + push(@implContentDecls, " return ${name}$overload->{overloadIndex}Callback(args);\n"); + } + push(@implContentDecls, <<END); + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); +END + push(@implContentDecls, "}\n\n"); +} + sub GenerateFunctionCallback { my $function = shift; my $dataNode = shift; - my $classIndex = shift; my $implClassName = shift; my $interfaceName = $dataNode->name; my $name = $function->signature->name; - push(@implContentDecls, -" static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args) {\n" . -" INC_STATS(\"DOM.$implClassName.$name\");\n"); + if (@{$function->{overloads}} > 1) { + # Append a number to an overloaded method's name to make it unique: + $name = $name . $function->{overloadIndex}; + } + + # Adding and removing event listeners are not standard callback behavior, + # but they are extremely consistent across the various classes that take event listeners, + # so we can generate them as a "special case". + if ($name eq "addEventListener") { + GenerateEventListenerCallback($implClassName, "add"); + return; + } elsif ($name eq "removeEventListener") { + GenerateEventListenerCallback($implClassName, "remove"); + return; + } + + push(@implContentDecls, <<END); +static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args) +{ + INC_STATS(\"DOM.$implClassName.$name\"); +END my $numParameters = @{$function->parameters}; if ($function->signature->extendedAttributes->{"RequiresAllArguments"}) { - push(@implContentDecls, - " if (args.Length() < $numParameters) return v8::Handle<v8::Value>();\n"); + push(@implContentDecls, " if (args.Length() < $numParameters)\n return v8::Handle<v8::Value>();\n"); } if (IsPodType($implClassName)) { my $nativeClassName = GetNativeType($implClassName); - push(@implContentDecls, " V8SVGPODTypeWrapper<$nativeClassName>* imp_wrapper = V8SVGPODTypeWrapper<$nativeClassName>::toNative(args.Holder());\n"); - push(@implContentDecls, " $nativeClassName imp_instance = *imp_wrapper;\n"); - push(@implContentDecls, " $nativeClassName* imp = &imp_instance;\n"); + push(@implContentDecls, " V8SVGPODTypeWrapper<$nativeClassName>* impWrapper = V8SVGPODTypeWrapper<$nativeClassName>::toNative(args.Holder());\n"); + push(@implContentDecls, " $nativeClassName impInstance = *impWrapper;\n"); + push(@implContentDecls, " $nativeClassName* imp = &impInstance;\n"); } else { push(@implContentDecls, <<END); ${implClassName}* imp = V8${implClassName}::toNative(args.Holder()); END } - # Check domain security if needed + # Check domain security if needed if (($dataNode->extendedAttributes->{"CheckDomainSecurity"} || $interfaceName eq "DOMWindow") && !$function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) { # We have not find real use cases yet. - push(@implContentDecls, -" if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true)) {\n". -" return v8::Handle<v8::Value>();\n" . -" }\n"); + push(@implContentDecls, <<END); + if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true)) + return v8::Handle<v8::Value>(); +END } my $raisesExceptions = @{$function->raisesExceptions}; @@ -1072,16 +1179,18 @@ END } if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) { - push(@implContentDecls, -" OwnPtr<ScriptCallStack> callStack(ScriptCallStack::create(args, $numParameters));\n". -" if (!callStack)\n". -" return v8::Undefined();\n"); + push(@implContentDecls, <<END); + OwnPtr<ScriptCallStack> callStack(ScriptCallStack::create(args, $numParameters)); + if (!callStack) + return v8::Undefined(); +END $implIncludes{"ScriptCallStack.h"} = 1; } if ($function->signature->extendedAttributes->{"SVGCheckSecurityDocument"}) { - push(@implContentDecls, -" if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->getSVGDocument(ec)))\n" . -" return v8::Handle<v8::Value>();\n"); + push(@implContentDecls, <<END); + if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->getSVGDocument(ec))) + return v8::Handle<v8::Value>(); +END } my $paramIndex = 0; @@ -1098,20 +1207,29 @@ END push(@implContentDecls, " }\n"); } - if (BasicTypeCanFailConversion($parameter)) { + if ($parameter->type eq "SerializedScriptValue") { + $implIncludes{"SerializedScriptValue.h"} = 1; + push(@implContentDecls, " bool ${parameterName}DidThrow = false;\n"); + } elsif (BasicTypeCanFailConversion($parameter)) { push(@implContentDecls, " bool ${parameterName}Ok;\n"); } push(@implContentDecls, " " . GetNativeTypeFromSignature($parameter, $paramIndex) . " $parameterName = "); - push(@implContentDecls, JSValueToNative($parameter, "args[$paramIndex]", - BasicTypeCanFailConversion($parameter) ? "${parameterName}Ok" : undef) . ";\n"); + + if ($parameter->type eq "SerializedScriptValue") { + push(@implContentDecls, "SerializedScriptValue::create(args[$paramIndex], ${parameterName}DidThrow);\n"); + push(@implContentDecls, " if (${parameterName}DidThrow)\n return v8::Undefined();\n"); + } else { + push(@implContentDecls, JSValueToNative($parameter, "args[$paramIndex]", + BasicTypeCanFailConversion($parameter) ? "${parameterName}Ok" : undef) . ";\n"); + } if (TypeCanFailConversion($parameter)) { $implIncludes{"ExceptionCode.h"} = 1; push(@implContentDecls, " if (UNLIKELY(!$parameterName" . (BasicTypeCanFailConversion($parameter) ? "Ok" : "") . ")) {\n" . -" ec = TYPE_MISMATCH_ERR;\n" . -" goto fail;\n" . +" ec = TYPE_MISMATCH_ERR;\n" . +" goto fail;\n" . " }\n"); } @@ -1119,8 +1237,8 @@ END $implIncludes{"ExceptionCode.h"} = 1; push(@implContentDecls, " if (UNLIKELY($parameterName < 0)) {\n" . -" ec = INDEX_SIZE_ERR;\n" . -" goto fail;\n" . +" ec = INDEX_SIZE_ERR;\n" . +" goto fail;\n" . " }\n"); } @@ -1133,12 +1251,12 @@ END if ($raisesExceptions) { push(@implContentDecls, " }\n"); - push(@implContentDecls, " fail:\n"); + push(@implContentDecls, " fail:\n"); push(@implContentDecls, " V8Proxy::setDOMException(ec);\n"); push(@implContentDecls, " return v8::Handle<v8::Value>();\n"); } - push(@implContentDecls, " }\n\n"); + push(@implContentDecls, "}\n\n"); } sub GenerateBatchedAttributeData @@ -1164,6 +1282,10 @@ sub GenerateSingleBatchedAttribute my $attrName = $attribute->signature->name; my $attrExt = $attribute->signature->extendedAttributes; + # Attributes of type SerializedScriptValue are set in the + # constructor and don't require callbacks. + return if ($attribute->signature->type eq "SerializedScriptValue"); + my $accessControl = "v8::DEFAULT"; if ($attrExt->{"DoNotCheckDomainSecurityOnGet"}) { $accessControl = "v8::ALL_CAN_READ"; @@ -1172,11 +1294,11 @@ sub GenerateSingleBatchedAttribute } elsif ($attrExt->{"DoNotCheckDomainSecurity"}) { $accessControl = "v8::ALL_CAN_READ"; if (!($attribute->type =~ /^readonly/) && !($attrExt->{"V8ReadOnly"})) { - $accessControl .= "|v8::ALL_CAN_WRITE"; + $accessControl .= " | v8::ALL_CAN_WRITE"; } } if ($attrExt->{"V8DisallowShadowing"}) { - $accessControl .= "|v8::PROHIBITS_OVERWRITING"; + $accessControl .= " | v8::PROHIBITS_OVERWRITING"; } $accessControl = "static_cast<v8::AccessControl>(" . $accessControl . ")"; @@ -1200,24 +1322,24 @@ sub GenerateSingleBatchedAttribute # Check attributes. if ($attrExt->{"DontEnum"}) { - $propAttr .= "|v8::DontEnum"; + $propAttr .= " | v8::DontEnum"; } if ($attrExt->{"V8DisallowShadowing"}) { - $propAttr .= "|v8::DontDelete"; + $propAttr .= " | v8::DontDelete"; } my $on_proto = "0 /* on instance */"; - my $data = "V8ClassIndex::INVALID_CLASS_INDEX /* no data */"; + my $data = "0 /* no data */"; # Constructor if ($attribute->signature->type =~ /Constructor$/) { my $constructorType = $codeGenerator->StripModule($attribute->signature->type); $constructorType =~ s/Constructor$//; - my $constructorIndex = uc($constructorType); + $implIncludes{"V8${constructorType}.h"} = 1; if ($customAccessor) { $getter = "V8${customAccessor}AccessorGetter"; } else { - $data = "V8ClassIndex::${constructorIndex}"; + $data = "&V8${constructorType}::info"; $getter = "${interfaceName}Internal::${interfaceName}ConstructorGetter"; } $setter = "0"; @@ -1247,7 +1369,7 @@ sub GenerateSingleBatchedAttribute # FIXME: Investigate whether we could treat window.top as replaceable # and allow shadowing without it being a security hole. if (!($interfaceName eq "DOMWindow" and $attrName eq "top")) { - $propAttr .= "|v8::ReadOnly"; + $propAttr .= " | v8::ReadOnly"; } } @@ -1264,17 +1386,8 @@ sub GenerateSingleBatchedAttribute my $commentInfo = "Attribute '$attrName' (Type: '" . $attribute->type . "' ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')"; - push(@implContent, $indent . " {\n"); - push(@implContent, $indent . " \/\/ $commentInfo\n"); - push(@implContent, $indent . " \"$attrName\",\n"); - push(@implContent, $indent . " $getter,\n"); - push(@implContent, $indent . " $setter,\n"); - push(@implContent, $indent . " $data,\n"); - push(@implContent, $indent . " $accessControl,\n"); - push(@implContent, $indent . " static_cast<v8::PropertyAttribute>($propAttr),\n"); - push(@implContent, $indent . " $on_proto\n"); - push(@implContent, $indent . " }" . $delimiter . "\n"); -END + push(@implContent, $indent . " \/\/ $commentInfo\n"); + push(@implContent, $indent . " {\"$attrName\", $getter, $setter, $data, $accessControl, static_cast<v8::PropertyAttribute>($propAttr), $on_proto}" . $delimiter . "\n"); } sub GenerateImplementationIndexer @@ -1326,17 +1439,16 @@ sub GenerateImplementationIndexer my $conversion = $indexer->extendedAttributes->{"ConvertNullStringTo"}; if ($conversion && $conversion eq "Null") { push(@implContent, <<END); - setCollectionStringOrNullIndexedGetter<${interfaceName}>(desc); + setCollectionStringOrNullIndexedGetter<${interfaceName}>(desc); END } else { push(@implContent, <<END); - setCollectionStringIndexedGetter<${interfaceName}>(desc); + setCollectionStringIndexedGetter<${interfaceName}>(desc); END } } else { - my $indexerClassIndex = uc($indexerType); push(@implContent, <<END); - setCollectionIndexedGetter<${interfaceName}, ${indexerType}>(desc, V8ClassIndex::${indexerClassIndex}); + setCollectionIndexedGetter<${interfaceName}, ${indexerType}>(desc); END # Include the header for this indexer type, because setCollectionIndexedGetter() requires toV8() for this type. $implIncludes{"V8${indexerType}.h"} = 1; @@ -1358,11 +1470,11 @@ END $hasDeleter = 0; } - push(@implContent, " desc->${setOn}Template()->SetIndexedPropertyHandler(V8${interfaceName}::indexedPropertyGetter"); + push(@implContent, " desc->${setOn}Template()->SetIndexedPropertyHandler(V8${interfaceName}::indexedPropertyGetter"); push(@implContent, $hasCustomSetter ? ", V8${interfaceName}::indexedPropertySetter" : ", 0"); push(@implContent, ", 0"); # IndexedPropertyQuery -- not being used at the moment. push(@implContent, $hasDeleter ? ", V8${interfaceName}::indexedPropertyDeleter" : ", 0"); - push(@implContent, ", nodeCollectionIndexedPropertyEnumerator<${interfaceName}>, v8::Integer::New(V8ClassIndex::NODE)") if $hasEnumerator; + push(@implContent, ", nodeCollectionIndexedPropertyEnumerator<${interfaceName}>") if $hasEnumerator; push(@implContent, ");\n"); } @@ -1380,6 +1492,10 @@ sub GenerateImplementationNamedPropertyGetter $hasCustomGetter = 1; } + if ($interfaceName eq "HTMLAppletElement" || $interfaceName eq "HTMLEmbedElement" || $interfaceName eq "HTMLObjectElement") { + $hasCustomGetter = 1; + } + my $hasGetter = $dataNode->extendedAttributes->{"HasNameGetter"} || $hasCustomGetter || $namedPropertyGetter; if (!$hasGetter) { return; @@ -1388,9 +1504,8 @@ sub GenerateImplementationNamedPropertyGetter if ($namedPropertyGetter && $namedPropertyGetter->type ne "Node" && !$namedPropertyGetter->extendedAttributes->{"Custom"} && !$hasCustomGetter) { $implIncludes{"V8Collection.h"} = 1; my $type = $namedPropertyGetter->type; - my $classIndex = uc($type); push(@implContent, <<END); - setCollectionNamedGetter<${interfaceName}, ${type}>(desc, V8ClassIndex::${classIndex}); + setCollectionNamedGetter<${interfaceName}, ${type}>(desc); END return; } @@ -1411,7 +1526,7 @@ END $hasEnumerator = 0; } - push(@implContent, " desc->${setOn}Template()->SetNamedPropertyHandler(V8${interfaceName}::namedPropertyGetter, "); + push(@implContent, " desc->${setOn}Template()->SetNamedPropertyHandler(V8${interfaceName}::namedPropertyGetter, "); push(@implContent, $hasSetter ? "V8${interfaceName}::namedPropertySetter, " : "0, "); push(@implContent, "0, "); # NamedPropertyQuery -- not being used at the moment. push(@implContent, $hasDeleter ? "V8${interfaceName}::namedPropertyDeleter, " : "0, "); @@ -1432,7 +1547,7 @@ sub GenerateImplementationCustomCall } if ($hasCustomCall) { - push(@implContent, " desc->InstanceTemplate()->SetCallAsFunctionHandler(V8${interfaceName}::callAsFunctionCallback);\n"); + push(@implContent, " desc->InstanceTemplate()->SetCallAsFunctionHandler(V8${interfaceName}::callAsFunctionCallback);\n"); } } @@ -1441,7 +1556,7 @@ sub GenerateImplementationMasqueradesAsUndefined my $dataNode = shift; if ($dataNode->extendedAttributes->{"MasqueradesAsUndefined"}) { - push(@implContent, " desc->InstanceTemplate()->MarkAsUndetectable();\n"); + push(@implContent, " desc->InstanceTemplate()->MarkAsUndetectable();\n"); } } @@ -1450,9 +1565,9 @@ sub GenerateImplementation my $object = shift; my $dataNode = shift; my $interfaceName = $dataNode->name; + my $visibleInterfaceName = GetVisibleInterfaceName($interfaceName); my $className = "V8$interfaceName"; my $implClassName = $interfaceName; - my $classIndex = uc($codeGenerator->StripModule($interfaceName)); my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"}; my $conditionalString = GenerateConditionalString($dataNode); @@ -1461,30 +1576,33 @@ sub GenerateImplementation @implContentHeader = split("\r", $headerTemplate); push(@implFixedHeader, - "#include \"config.h\"\n" . - "#include \"RuntimeEnabledFeatures.h\"\n" . - "#include \"V8Proxy.h\"\n" . - "#include \"V8Binding.h\"\n" . - "#include \"V8BindingState.h\"\n" . - "#include \"V8DOMWrapper.h\"\n" . - "#include \"V8IsolatedContext.h\"\n\n" . - "#undef LOG\n\n"); + "\n#include \"config.h\"\n" . + "#include \"${className}.h\"\n\n"); push(@implFixedHeader, "\n#if ${conditionalString}\n\n") if $conditionalString; + + $implIncludes{"RuntimeEnabledFeatures.h"} = 1; + $implIncludes{"V8Proxy.h"} = 1; + $implIncludes{"V8Binding.h"} = 1; + $implIncludes{"V8BindingState.h"} = 1; + $implIncludes{"V8DOMWrapper.h"} = 1; + $implIncludes{"V8IsolatedContext.h"} = 1; if ($className =~ /^V8SVGAnimated/) { AddIncludesForSVGAnimatedType($interfaceName); } - $implIncludes{"${className}.h"} = 1; - AddIncludesForType($interfaceName); - push(@implContentDecls, "namespace WebCore {\n"); + my $toActive = IsActiveDomType($interfaceName) ? "${className}::toActiveDOMObject" : "0"; + + push(@implContentDecls, "namespace WebCore {\n\n"); + push(@implContentDecls, "WrapperTypeInfo ${className}::info = { ${className}::GetTemplate, ${className}::derefObject, ${toActive} };\n\n"); push(@implContentDecls, "namespace ${interfaceName}Internal {\n\n"); push(@implContentDecls, "template <typename T> void V8_USE(T) { }\n\n"); my $hasConstructors = 0; + my $serializedAttribute; # Generate property accessors for attributes. for ($index = 0; $index < @{$dataNode->attributes}; $index++) { $attribute = @{$dataNode->attributes}[$index]; @@ -1504,6 +1622,15 @@ sub GenerateImplementation $attribute->signature->extendedAttributes->{"v8OnProto"} = 1; } + # Attributes of type SerializedScriptValue are set in the + # constructor and don't require callbacks. + if ($attrType eq "SerializedScriptValue") { + die "Only one attribute of type SerializedScriptValue supported" if $serializedAttribute; + $implIncludes{"SerializedScriptValue.h"} = 1; + $serializedAttribute = $attribute; + next; + } + # Do not generate accessor if this is a custom attribute. The # call will be forwarded to a hand-written accessor # implementation. @@ -1517,29 +1644,30 @@ sub GenerateImplementation $attribute->signature->extendedAttributes->{"V8CustomGetter"})) { GenerateNormalAttrGetter($attribute, $dataNode, $implClassName, $interfaceName); } - if (!($attribute->signature->extendedAttributes->{"CustomSetter"} || - $attribute->signature->extendedAttributes->{"V8CustomSetter"})) { - if ($attribute->signature->extendedAttributes->{"Replaceable"}) { - $dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"} || die "Replaceable attribute can only be used in interface that defines ExtendsDOMGlobalObject attribute!"; - # GenerateReplaceableAttrSetter($implClassName); - } elsif ($attribute->type !~ /^readonly/ && !$attribute->signature->extendedAttributes->{"V8ReadOnly"}) { - GenerateNormalAttrSetter($attribute, $dataNode, $implClassName, $interfaceName); - } + if (!$attribute->signature->extendedAttributes->{"CustomSetter"} && + !$attribute->signature->extendedAttributes->{"V8CustomSetter"} && + !$attribute->signature->extendedAttributes->{"Replaceable"} && + $attribute->type !~ /^readonly/ && + !$attribute->signature->extendedAttributes->{"V8ReadOnly"}) { + GenerateNormalAttrSetter($attribute, $dataNode, $implClassName, $interfaceName); } } if ($hasConstructors) { - GenerateConstructorGetter($implClassName, $classIndex); + GenerateConstructorGetter($implClassName); } + LinkOverloadedFunctions($dataNode); + my $indexer; my $namedPropertyGetter; # Generate methods for functions. foreach my $function (@{$dataNode->functions}) { - # hack for addEventListener/RemoveEventListener - # FIXME: avoid naming conflict if (!($function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"V8Custom"})) { - GenerateFunctionCallback($function, $dataNode, $classIndex, $implClassName); + GenerateFunctionCallback($function, $dataNode, $implClassName); + if ($function->{overloadIndex} > 1 && $function->{overloadIndex} == @{$function->{overloads}}) { + GenerateOverloadedFunctionCallback($function, $dataNode, $implClassName); + } } if ($function->signature->name eq "item") { @@ -1554,7 +1682,7 @@ sub GenerateImplementation # generate an access getter that returns different function objects # for different calling context. if (($dataNode->extendedAttributes->{"CheckDomainSecurity"} || ($interfaceName eq "DOMWindow")) && $function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) { - GenerateDomainSafeFunctionGetter($function, $dataNode, $implClassName); + GenerateDomainSafeFunctionGetter($function, $implClassName); } } @@ -1580,7 +1708,7 @@ sub GenerateImplementation $attributes = \@normal; # Put the attributes that disallow shadowing on the shadow object. if (@disallowsShadowing) { - push(@implContent, "static const BatchedAttribute shadow_attrs[] = {\n"); + push(@implContent, "static const BatchedAttribute shadowAttrs[] = {\n"); GenerateBatchedAttributeData($dataNode, \@disallowsShadowing); push(@implContent, "};\n"); } @@ -1588,7 +1716,7 @@ sub GenerateImplementation my $has_attributes = 0; if (@$attributes) { $has_attributes = 1; - push(@implContent, "static const BatchedAttribute ${interfaceName}_attrs[] = {\n"); + push(@implContent, "static const BatchedAttribute ${interfaceName}Attrs[] = {\n"); GenerateBatchedAttributeData($dataNode, $attributes); push(@implContent, "};\n"); } @@ -1597,6 +1725,9 @@ sub GenerateImplementation $num_callbacks = 0; $has_callbacks = 0; foreach my $function (@{$dataNode->functions}) { + # Only one table entry is needed for overloaded methods: + next if $function->{overloadIndex} > 1; + my $attrExt = $function->signature->extendedAttributes; # Don't put any nonstandard functions into this table: if ($attrExt->{"V8OnInstance"}) { @@ -1614,12 +1745,12 @@ sub GenerateImplementation } if (!$has_callbacks) { $has_callbacks = 1; - push(@implContent, "static const BatchedCallback ${interfaceName}_callbacks[] = {\n"); + push(@implContent, "static const BatchedCallback ${interfaceName}Callbacks[] = {\n"); } my $name = $function->signature->name; - my $callback = GetFunctionTemplateCallbackName($function, $dataNode); + my $callback = GetFunctionTemplateCallbackName($function, $interfaceName); push(@implContent, <<END); - {"$name", $callback}, + {"$name", $callback}, END $num_callbacks++; } @@ -1629,7 +1760,7 @@ END my $has_constants = 0; if (@{$dataNode->constants}) { $has_constants = 1; - push(@implContent, "static const BatchedConstant ${interfaceName}_consts[] = {\n"); + push(@implContent, "static const BatchedConstant ${interfaceName}Consts[] = {\n"); } foreach my $constant (@{$dataNode->constants}) { my $name = $constant->name; @@ -1638,7 +1769,7 @@ END # defines "const unsigned long SHOW_ALL = 0xFFFFFFFF". It would be better if we # handled this here, and converted it to a -1 constant in the c++ output. push(@implContent, <<END); - { "${name}", static_cast<signed int>($value) }, + {"${name}", static_cast<signed int>($value)}, END } if ($has_constants) { @@ -1650,33 +1781,31 @@ END # In namespace WebCore, add generated implementation for 'CanBeConstructed'. if ($dataNode->extendedAttributes->{"CanBeConstructed"} && !$dataNode->extendedAttributes->{"CustomConstructor"}) { push(@implContent, <<END); - v8::Handle<v8::Value> ${className}::constructorCallback(const v8::Arguments& args) - { +v8::Handle<v8::Value> ${className}::constructorCallback(const v8::Arguments& args) +{ INC_STATS("DOM.${interfaceName}.Contructor"); - return V8Proxy::constructDOMObject<V8ClassIndex::${classIndex}, $interfaceName>(args); - } + return V8Proxy::constructDOMObject<$interfaceName>(args, &info); +} END } my $access_check = ""; if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && !($interfaceName eq "DOMWindow")) { - $access_check = "instance->SetAccessCheckCallbacks(V8${interfaceName}::namedSecurityCheck, V8${interfaceName}::indexedSecurityCheck, v8::Integer::New(V8ClassIndex::ToInt(V8ClassIndex::${classIndex})));"; + $access_check = "instance->SetAccessCheckCallbacks(V8${interfaceName}::namedSecurityCheck, V8${interfaceName}::indexedSecurityCheck, v8::External::Wrap(&V8${interfaceName}::info));"; } # For the DOMWindow interface, generate the shadow object template # configuration method. if ($implClassName eq "DOMWindow") { push(@implContent, <<END); -static v8::Persistent<v8::ObjectTemplate> ConfigureShadowObjectTemplate(v8::Persistent<v8::ObjectTemplate> templ) { - batchConfigureAttributes(templ, - v8::Handle<v8::ObjectTemplate>(), - shadow_attrs, - sizeof(shadow_attrs)/sizeof(*shadow_attrs)); +static v8::Persistent<v8::ObjectTemplate> ConfigureShadowObjectTemplate(v8::Persistent<v8::ObjectTemplate> templ) +{ + batchConfigureAttributes(templ, v8::Handle<v8::ObjectTemplate>(), shadowAttrs, sizeof(shadowAttrs) / sizeof(*shadowAttrs)); - // Install a security handler with V8. - templ->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::Integer::New(V8ClassIndex::DOMWINDOW)); - templ->SetInternalFieldCount(V8DOMWindow::internalFieldCount); - return templ; + // Install a security handler with V8. + templ->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::External::Wrap(&V8DOMWindow::info)); + templ->SetInternalFieldCount(V8DOMWindow::internalFieldCount); + return templ; } END } @@ -1696,45 +1825,45 @@ END # Generate the template configuration method push(@implContent, <<END); -static v8::Persistent<v8::FunctionTemplate> Configure${className}Template(v8::Persistent<v8::FunctionTemplate> desc) { - v8::Local<v8::Signature> default_signature = configureTemplate(desc, \"${interfaceName}\", - $parentClassTemplate, V8${interfaceName}::internalFieldCount, +static v8::Persistent<v8::FunctionTemplate> Configure${className}Template(v8::Persistent<v8::FunctionTemplate> desc) +{ + v8::Local<v8::Signature> defaultSignature = configureTemplate(desc, \"${visibleInterfaceName}\", $parentClassTemplate, V8${interfaceName}::internalFieldCount, END # Set up our attributes if we have them if ($has_attributes) { push(@implContent, <<END); - ${interfaceName}_attrs, sizeof(${interfaceName}_attrs)/sizeof(*${interfaceName}_attrs), + ${interfaceName}Attrs, sizeof(${interfaceName}Attrs) / sizeof(*${interfaceName}Attrs), END } else { push(@implContent, <<END); - NULL, 0, + 0, 0, END } if ($has_callbacks) { push(@implContent, <<END); - ${interfaceName}_callbacks, sizeof(${interfaceName}_callbacks)/sizeof(*${interfaceName}_callbacks)); + ${interfaceName}Callbacks, sizeof(${interfaceName}Callbacks) / sizeof(*${interfaceName}Callbacks)); END } else { push(@implContent, <<END); - NULL, 0); + 0, 0); END } if ($dataNode->extendedAttributes->{"CustomConstructor"} || $dataNode->extendedAttributes->{"CanBeConstructed"}) { push(@implContent, <<END); - desc->SetCallHandler(V8${interfaceName}::constructorCallback); + desc->SetCallHandler(V8${interfaceName}::constructorCallback); END } if ($access_check or @enabledAtRuntime or @{$dataNode->functions} or $has_constants) { push(@implContent, <<END); - v8::Local<v8::ObjectTemplate> instance = desc->InstanceTemplate(); - v8::Local<v8::ObjectTemplate> proto = desc->PrototypeTemplate(); + v8::Local<v8::ObjectTemplate> instance = desc->InstanceTemplate(); + v8::Local<v8::ObjectTemplate> proto = desc->PrototypeTemplate(); END } - push(@implContent, " $access_check\n"); + push(@implContent, " $access_check\n"); # Setup the enable-at-runtime attrs if we have them foreach my $runtime_attr (@enabledAtRuntime) { @@ -1760,16 +1889,19 @@ END # Define our functions with Set() or SetAccessor() $total_functions = 0; foreach my $function (@{$dataNode->functions}) { + # Only one accessor is needed for overloaded methods: + next if $function->{overloadIndex} > 1; + $total_functions++; my $attrExt = $function->signature->extendedAttributes; my $name = $function->signature->name; my $property_attributes = "v8::DontDelete"; if ($attrExt->{"DontEnum"}) { - $property_attributes .= "|v8::DontEnum"; + $property_attributes .= " | v8::DontEnum"; } if ($attrExt->{"V8ReadOnly"}) { - $property_attributes .= "|v8::ReadOnly"; + $property_attributes .= " | v8::ReadOnly"; } my $commentInfo = "Function '$name' (ExtAttr: '" . join(' ', keys(%{$attrExt})) . "')"; @@ -1783,7 +1915,7 @@ END if ($attrExt->{"EnabledAtRuntime"}) { # Only call Set()/SetAccessor() if this method should be enabled $enable_function = "RuntimeEnabledFeatures::" . $codeGenerator->WK_lcfirst($function->signature->name) . "Enabled"; - $conditional = "if (${enable_function}())\n"; + $conditional = "if (${enable_function}())\n "; } if ($attrExt->{"DoNotCheckDomainSecurity"} && @@ -1802,34 +1934,28 @@ END # # The solution is very hacky and fragile, it really needs to be replaced # by a better solution. - $property_attributes .= "|v8::ReadOnly"; + $property_attributes .= " | v8::ReadOnly"; push(@implContent, <<END); - // $commentInfo - $conditional $template->SetAccessor( - v8::String::New("$name"), - ${interfaceName}Internal::${name}AttrGetter, - 0, - v8::Handle<v8::Value>(), - v8::ALL_CAN_READ, - static_cast<v8::PropertyAttribute>($property_attributes)); + // $commentInfo + ${conditional}$template->SetAccessor(v8::String::New("$name"), ${interfaceName}Internal::${name}AttrGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>($property_attributes)); END $num_callbacks++; next; } - my $signature = "default_signature"; - if ($attrExt->{"V8DoNotCheckSignature"}){ + my $signature = "defaultSignature"; + if ($attrExt->{"V8DoNotCheckSignature"}) { $signature = "v8::Local<v8::Signature>()"; } if (RequiresCustomSignature($function)) { - $signature = "${name}_signature"; - push(@implContent, "\n // Custom Signature '$name'\n", CreateCustomSignature($function)); + $signature = "${name}Signature"; + push(@implContent, "\n // Custom Signature '$name'\n", CreateCustomSignature($function)); } # Normal function call is a template - my $callback = GetFunctionTemplateCallbackName($function, $dataNode); + my $callback = GetFunctionTemplateCallbackName($function, $interfaceName); if ($property_attributes eq "v8::DontDelete") { $property_attributes = ""; @@ -1837,13 +1963,13 @@ END $property_attributes = ", static_cast<v8::PropertyAttribute>($property_attributes)"; } - if ($template eq "proto" && $conditional eq "" && $signature eq "default_signature" && $property_attributes eq "") { + if ($template eq "proto" && $conditional eq "" && $signature eq "defaultSignature" && $property_attributes eq "") { # Standard type of callback, already created in the batch, so skip it here. next; } push(@implContent, <<END); - ${conditional}$template->Set(v8::String::New("$name"), v8::FunctionTemplate::New($callback, v8::Handle<v8::Value>(), ${signature})$property_attributes); + ${conditional}$template->Set(v8::String::New("$name"), v8::FunctionTemplate::New($callback, v8::Handle<v8::Value>(), ${signature})$property_attributes); END $num_callbacks++; } @@ -1852,7 +1978,7 @@ END if ($has_constants) { push(@implContent, <<END); - batchConfigureConstants(desc, proto, ${interfaceName}_consts, sizeof(${interfaceName}_consts)/sizeof(*${interfaceName}_consts)); + batchConfigureConstants(desc, proto, ${interfaceName}Consts, sizeof(${interfaceName}Consts) / sizeof(*${interfaceName}Consts)); END } @@ -1860,23 +1986,23 @@ END if ($interfaceName eq "DOMWindow") { push(@implContent, <<END); - proto->SetInternalFieldCount(V8DOMWindow::internalFieldCount); - desc->SetHiddenPrototype(true); - instance->SetInternalFieldCount(V8DOMWindow::internalFieldCount); - // Set access check callbacks, but turned off initially. - // When a context is detached from a frame, turn on the access check. - // Turning on checks also invalidates inline caches of the object. - instance->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::Integer::New(V8ClassIndex::DOMWINDOW), false); + proto->SetInternalFieldCount(V8DOMWindow::internalFieldCount); + desc->SetHiddenPrototype(true); + instance->SetInternalFieldCount(V8DOMWindow::internalFieldCount); + // Set access check callbacks, but turned off initially. + // When a context is detached from a frame, turn on the access check. + // Turning on checks also invalidates inline caches of the object. + instance->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::External::Wrap(&V8DOMWindow::info), false); END } if ($interfaceName eq "Location") { push(@implContent, <<END); - // For security reasons, these functions are on the instance instead - // of on the prototype object to insure that they cannot be overwritten. - instance->SetAccessor(v8::String::New("reload"), V8Location::reloadAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly)); - instance->SetAccessor(v8::String::New("replace"), V8Location::replaceAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly)); - instance->SetAccessor(v8::String::New("assign"), V8Location::assignAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly)); + // For security reasons, these functions are on the instance instead + // of on the prototype object to ensure that they cannot be overwritten. + instance->SetAccessor(v8::String::New("reload"), V8Location::reloadAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly)); + instance->SetAccessor(v8::String::New("replace"), V8Location::replaceAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly)); + instance->SetAccessor(v8::String::New("assign"), V8Location::assignAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly)); END } @@ -1886,51 +2012,86 @@ END } push(@implContent, <<END); - // Custom toString template - desc->Set(getToStringName(), getToStringTemplate()); - return desc; + // Custom toString template + desc->Set(getToStringName(), getToStringTemplate()); + return desc; } -v8::Persistent<v8::FunctionTemplate> ${className}::GetRawTemplate() { - static v8::Persistent<v8::FunctionTemplate> ${className}_raw_cache_ = createRawTemplate(); - return ${className}_raw_cache_; +v8::Persistent<v8::FunctionTemplate> ${className}::GetRawTemplate() +{ + static v8::Persistent<v8::FunctionTemplate> ${className}RawCache = createRawTemplate(); + return ${className}RawCache; } -v8::Persistent<v8::FunctionTemplate> ${className}::GetTemplate() { - static v8::Persistent<v8::FunctionTemplate> ${className}_cache_ = Configure${className}Template(GetRawTemplate()); - return ${className}_cache_; +v8::Persistent<v8::FunctionTemplate> ${className}::GetTemplate()\ +{ + static v8::Persistent<v8::FunctionTemplate> ${className}Cache = Configure${className}Template(GetRawTemplate()); + return ${className}Cache; } -${nativeType}* ${className}::toNative(v8::Handle<v8::Object> object) { - return reinterpret_cast<${nativeType}*>(object->GetPointerFromInternalField(v8DOMWrapperObjectIndex)); +${nativeType}* ${className}::toNative(v8::Handle<v8::Object> object) +{ + return reinterpret_cast<${nativeType}*>(object->GetPointerFromInternalField(v8DOMWrapperObjectIndex)); } -bool ${className}::HasInstance(v8::Handle<v8::Value> value) { - return GetRawTemplate()->HasInstance(value); +bool ${className}::HasInstance(v8::Handle<v8::Value> value) +{ + return GetRawTemplate()->HasInstance(value); } END + if (IsActiveDomType($interfaceName)) { + # MessagePort is handled like an active dom object even though it doesn't inherit + # from ActiveDOMObject, so don't try to cast it to ActiveDOMObject. + my $returnValue = $interfaceName eq "MessagePort" ? "0" : "toNative(object)"; + push(@implContent, <<END); +ActiveDOMObject* ${className}::toActiveDOMObject(v8::Handle<v8::Object> object) +{ + return ${returnValue}; +} +END + } + if ($implClassName eq "DOMWindow") { push(@implContent, <<END); -v8::Persistent<v8::ObjectTemplate> V8DOMWindow::GetShadowObjectTemplate() { - static v8::Persistent<v8::ObjectTemplate> V8DOMWindowShadowObject_cache_; - if (V8DOMWindowShadowObject_cache_.IsEmpty()) { - V8DOMWindowShadowObject_cache_ = v8::Persistent<v8::ObjectTemplate>::New(v8::ObjectTemplate::New()); - ConfigureShadowObjectTemplate(V8DOMWindowShadowObject_cache_); - } - return V8DOMWindowShadowObject_cache_; +v8::Persistent<v8::ObjectTemplate> V8DOMWindow::GetShadowObjectTemplate() +{ + static v8::Persistent<v8::ObjectTemplate> V8DOMWindowShadowObjectCache; + if (V8DOMWindowShadowObjectCache.IsEmpty()) { + V8DOMWindowShadowObjectCache = v8::Persistent<v8::ObjectTemplate>::New(v8::ObjectTemplate::New()); + ConfigureShadowObjectTemplate(V8DOMWindowShadowObjectCache); + } + return V8DOMWindowShadowObjectCache; } END } - GenerateToV8Converters($dataNode, $interfaceName, $className, $nativeType); + GenerateToV8Converters($dataNode, $interfaceName, $className, $nativeType, $serializedAttribute); + + push(@implContent, <<END); + +void ${className}::derefObject(void* object) +{ +END + + if (IsRefPtrType($interfaceName)) { + push(@implContent, <<END); + static_cast<${nativeType}*>(object)->deref(); +END + } push(@implContent, <<END); +} + } // namespace WebCore END push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString; + + # We've already added the header for this file in implFixedHeader, so remove + # it from implIncludes to ensure we don't #include it twice. + delete $implIncludes{"${className}.h"}; } sub GenerateToV8Converters @@ -1939,90 +2100,107 @@ sub GenerateToV8Converters my $interfaceName = shift; my $className = shift; my $nativeType = shift; + my $serializedAttribute = shift; - my $wrapperType = "V8ClassIndex::" . uc($interfaceName); my $domMapFunction = GetDomMapFunction($dataNode, $interfaceName); my $forceNewObjectInput = IsDOMNodeType($interfaceName) ? ", bool forceNewObject" : ""; my $forceNewObjectCall = IsDOMNodeType($interfaceName) ? ", forceNewObject" : ""; push(@implContent, <<END); -v8::Handle<v8::Object> ${className}::wrap(${nativeType}* impl${forceNewObjectInput}) { - v8::Handle<v8::Object> wrapper; - V8Proxy* proxy = 0; +v8::Handle<v8::Object> ${className}::wrap(${nativeType}* impl${forceNewObjectInput}) +{ + v8::Handle<v8::Object> wrapper; + V8Proxy* proxy = 0; END if (IsNodeSubType($dataNode)) { push(@implContent, <<END); - if (impl->document()) { - proxy = V8Proxy::retrieve(impl->document()->frame()); - if (proxy && static_cast<Node*>(impl->document()) == static_cast<Node*>(impl)) - proxy->windowShell()->initContextIfNeeded(); - } + if (impl->document()) { + proxy = V8Proxy::retrieve(impl->document()->frame()); + if (proxy && static_cast<Node*>(impl->document()) == static_cast<Node*>(impl)) + proxy->windowShell()->initContextIfNeeded(); + } END } if ($domMapFunction) { - push(@implContent, " if (!forceNewObject) {\n") if IsDOMNodeType($interfaceName); + push(@implContent, " if (!forceNewObject) {\n") if IsDOMNodeType($interfaceName); if (IsNodeSubType($dataNode)) { - push(@implContent, " wrapper = V8DOMWrapper::getWrapper(impl);\n"); + push(@implContent, " wrapper = V8DOMWrapper::getWrapper(impl);\n"); } else { - push(@implContent, " wrapper = ${domMapFunction}.get(impl);\n"); + push(@implContent, " wrapper = ${domMapFunction}.get(impl);\n"); } push(@implContent, <<END); - if (!wrapper.IsEmpty()) - return wrapper; + if (!wrapper.IsEmpty()) + return wrapper; END - push(@implContent, " }\n") if IsDOMNodeType($interfaceName); + push(@implContent, " }\n") if IsDOMNodeType($interfaceName); } if (IsNodeSubType($dataNode)) { push(@implContent, <<END); - v8::Handle<v8::Context> context; - if (proxy) - context = proxy->context(); + v8::Handle<v8::Context> context; + if (proxy) + context = proxy->context(); - // Enter the node's context and create the wrapper in that context. - if (!context.IsEmpty()) - context->Enter(); + // Enter the node's context and create the wrapper in that context. + if (!context.IsEmpty()) + context->Enter(); END } push(@implContent, <<END); - wrapper = V8DOMWrapper::instantiateV8Object(proxy, ${wrapperType}, impl); + wrapper = V8DOMWrapper::instantiateV8Object(proxy, &info, impl); END - if (IsNodeSubType($dataNode)) { push(@implContent, <<END); - // Exit the node's context if it was entered. - if (!context.IsEmpty()) - context->Exit(); + // Exit the node's context if it was entered. + if (!context.IsEmpty()) + context->Exit(); END } push(@implContent, <<END); - if (wrapper.IsEmpty()) - return wrapper; + if (wrapper.IsEmpty()) + return wrapper; +END + push(@implContent, "\n impl->ref();\n") if IsRefPtrType($interfaceName); + + # Eagerly deserialize attributes of type SerializedScriptValue + # while we're in the right context. + if ($serializedAttribute) { + die "Attribute of type SerializedScriptValue expected" if $serializedAttribute->signature->type ne "SerializedScriptValue"; + my $attrName = $serializedAttribute->signature->name; + my $attrAttr = "v8::DontDelete"; + if ($serializedAttribute->type =~ /^readonly/) { + $attrAttr .= " | v8::ReadOnly"; + } + $attrAttr = "static_cast<v8::PropertyAttribute>($attrAttr)"; + my $getterFunc = $codeGenerator->WK_lcfirst($attrName); + push(@implContent, <<END); + SerializedScriptValue::deserializeAndSetProperty(wrapper, "${attrName}", ${attrAttr}, impl->${getterFunc}()); END - push(@implContent, "\n impl->ref();\n") if IsRefPtrType($interfaceName); + } if ($domMapFunction) { push(@implContent, <<END); - ${domMapFunction}.set(impl, v8::Persistent<v8::Object>::New(wrapper)); + ${domMapFunction}.set(impl, v8::Persistent<v8::Object>::New(wrapper)); END } push(@implContent, <<END); - return wrapper; + return wrapper; } END if (IsRefPtrType($interfaceName)) { push(@implContent, <<END); -v8::Handle<v8::Value> toV8(PassRefPtr<${nativeType} > impl${forceNewObjectInput}) { - return toV8(impl.get()${forceNewObjectCall}); +v8::Handle<v8::Value> toV8(PassRefPtr<${nativeType} > impl${forceNewObjectInput}) +{ + return toV8(impl.get()${forceNewObjectCall}); } END } @@ -2030,10 +2208,11 @@ END if (!HasCustomToV8Implementation($dataNode, $interfaceName)) { push(@implContent, <<END); -v8::Handle<v8::Value> toV8(${nativeType}* impl${forceNewObjectInput}) { - if (!impl) - return v8::Null(); - return ${className}::wrap(impl${forceNewObjectCall}); +v8::Handle<v8::Value> toV8(${nativeType}* impl${forceNewObjectInput}) +{ + if (!impl) + return v8::Null(); + return ${className}::wrap(impl${forceNewObjectCall}); } END } @@ -2045,21 +2224,18 @@ sub HasCustomToV8Implementation { $interfaceName = shift; # We generate a custom converter (but JSC doesn't) for the following: - return 1 if $interfaceName eq "BarInfo"; return 1 if $interfaceName eq "CSSStyleSheet"; return 1 if $interfaceName eq "CanvasPixelArray"; - return 1 if $interfaceName eq "DOMSelection"; return 1 if $interfaceName eq "DOMWindow"; return 1 if $interfaceName eq "Element"; - return 1 if $interfaceName eq "Location"; return 1 if $interfaceName eq "HTMLDocument"; return 1 if $interfaceName eq "HTMLElement"; - return 1 if $interfaceName eq "History"; + return 1 if $interfaceName eq "Location"; return 1 if $interfaceName eq "NamedNodeMap"; - return 1 if $interfaceName eq "Navigator"; return 1 if $interfaceName eq "SVGDocument"; return 1 if $interfaceName eq "SVGElement"; - return 1 if $interfaceName eq "Screen"; + return 1 if $interfaceName eq "ScriptProfile"; + return 1 if $interfaceName eq "ScriptProfileNode"; return 1 if $interfaceName eq "WorkerContext"; # We don't generate a custom converter (but JSC does) for the following: return 0 if $interfaceName eq "AbstractWorker"; @@ -2076,7 +2252,7 @@ sub GetDomMapFunction my $dataNode = shift; my $type = shift; return "getDOMSVGElementInstanceMap()" if $type eq "SVGElementInstance"; - return "getDOMNodeMap()" if IsNodeSubType($dataNode); + return "getDOMNodeMap()" if ($dataNode && IsNodeSubType($dataNode)); # Only use getDOMSVGObjectWithContextMap() for non-node svg objects return "getDOMSVGObjectWithContextMap()" if $type =~ /SVG/; return "" if $type eq "DOMImplementation"; @@ -2088,6 +2264,7 @@ sub IsActiveDomType { # FIXME: Consider making this an .idl attribute. my $type = shift; + return 1 if $type eq "EventSource"; return 1 if $type eq "MessagePort"; return 1 if $type eq "XMLHttpRequest"; return 1 if $type eq "WebSocket"; @@ -2201,9 +2378,7 @@ sub GenerateFunctionCallString() if ($returnType eq "void") { $result .= $indent . "$functionString;\n"; } elsif ($copyFirst) { - $result .= - $indent . GetNativeType($returnType, 0) . " result = *imp;\n" . - $indent . "$functionString;\n"; + $result .= $indent . GetNativeType($returnType, 0) . " result = *imp;\n" . $indent . "$functionString;\n"; } elsif ($returnsListItemPodType) { $result .= $indent . "RefPtr<SVGPODListItem<$nativeReturnType> > result = $functionString;\n"; } elsif (@{$function->raisesExceptions} or $returnsPodType or $isPodType or IsSVGTypeNeedingContextParameter($returnType)) { @@ -2215,7 +2390,7 @@ sub GenerateFunctionCallString() } if (@{$function->raisesExceptions}) { - $result .= $indent . "if (UNLIKELY(ec)) goto fail;\n"; + $result .= $indent . "if (UNLIKELY(ec))\n" . $indent . " goto fail;\n"; } # If the return type is a POD type, separate out the wrapper generation @@ -2253,7 +2428,7 @@ sub GenerateFunctionCallString() $generatedSVGContextRetrieval = 1; } - $result .= $indent . "imp_wrapper->commitChange(imp_instance, context);\n"; + $result .= $indent . "impWrapper->commitChange(impInstance, context);\n"; } if ($returnsPodType) { @@ -2355,6 +2530,7 @@ sub GetNativeType return "unsigned" if $type eq "unsigned int"; return "Node*" if $type eq "EventTarget" and $isParameter; return "double" if $type eq "Date"; + return "ScriptValue" if $type eq "DOMObject"; return "String" if $type eq "DOMUserData"; # FIXME: Temporary hack? @@ -2370,75 +2546,6 @@ sub GetNativeType return "${type}*"; } - -my %typeCanFailConversion = ( - "Attr" => 1, - "WebGLArray" => 0, - "WebGLBuffer" => 0, - "WebGLByteArray" => 0, - "WebGLUnsignedByteArray" => 0, - "WebGLContextAttributes" => 0, - "WebGLFloatArray" => 0, - "WebGLFramebuffer" => 0, - "CanvasGradient" => 0, - "WebGLIntArray" => 0, - "CanvasPixelArray" => 0, - "WebGLProgram" => 0, - "WebGLRenderbuffer" => 0, - "WebGLShader" => 0, - "WebGLShortArray" => 0, - "WebGLTexture" => 0, - "WebGLUniformLocation" => 0, - "CompareHow" => 0, - "DataGridColumn" => 0, - "DOMString" => 0, - "DOMWindow" => 0, - "DocumentType" => 0, - "Element" => 0, - "Event" => 0, - "EventListener" => 0, - "EventTarget" => 0, - "HTMLCanvasElement" => 0, - "HTMLElement" => 0, - "HTMLImageElement" => 0, - "HTMLOptionElement" => 0, - "HTMLVideoElement" => 0, - "Node" => 0, - "NodeFilter" => 0, - "MessagePort" => 0, - "NSResolver" => 0, - "Range" => 0, - "SQLResultSet" => 0, - "Storage" => 0, - "SVGAngle" => 1, - "SVGElement" => 0, - "SVGLength" => 1, - "SVGMatrix" => 1, - "SVGNumber" => 0, - "SVGPaintType" => 0, - "SVGPathSeg" => 0, - "SVGPoint" => 1, - "SVGPreserveAspectRatio" => 1, - "SVGRect" => 1, - "SVGTransform" => 1, - "TouchList" => 0, - "VoidCallback" => 1, - "WebKitCSSMatrix" => 0, - "WebKitPoint" => 0, - "XPathEvaluator" => 0, - "XPathNSResolver" => 0, - "XPathResult" => 0, - "boolean" => 0, - "double" => 0, - "float" => 0, - "long" => 0, - "unsigned long" => 0, - "unsigned short" => 0, - "long long" => 0, - "unsigned long long" => 0 -); - - sub TranslateParameter { my $signature = shift; @@ -2471,10 +2578,9 @@ sub TypeCanFailConversion my $type = GetTypeFromSignature($signature); $implIncludes{"ExceptionCode.h"} = 1 if $type eq "Attr"; - - return $typeCanFailConversion{$type} if exists $typeCanFailConversion{$type}; - - die "Don't know whether a JS value can fail conversion to type $type."; + return 1 if $type eq "Attr"; + return 1 if $type eq "VoidCallback"; + return BasicTypeCanFailConversion($signature); } sub JSValueToNative @@ -2501,9 +2607,11 @@ sub JSValueToNative return $value; } - if ($type eq "SerializedScriptValue") { - $implIncludes{"SerializedScriptValue.h"} = 1; - return "SerializedScriptValue::create($value)"; + die "Unexpected SerializedScriptValue" if $type eq "SerializedScriptValue"; + + if ($type eq "DOMObject") { + $implIncludes{"ScriptValue.h"} = 1; + return "ScriptValue($value)"; } if ($type eq "NodeFilter") { @@ -2539,17 +2647,13 @@ sub JSValueToNative # return NULL. return "V8${type}::HasInstance($value) ? V8${type}::toNative(v8::Handle<v8::Object>::Cast($value)) : 0"; } else { - # TODO: Temporary to avoid Window name conflict. - my $classIndex = uc($type); - my $implClassName = ${type}; - $implIncludes{"V8$type.h"} = 1; if (IsPodType($type)) { my $nativeType = GetNativeType($type); $implIncludes{"V8SVGPODTypeWrapper.h"} = 1; - return "V8SVGPODTypeUtil::toSVGPODType<${nativeType}>(V8ClassIndex::${classIndex}, $value${maybeOkParam})" + return "V8SVGPODTypeUtil::toSVGPODType<${nativeType}>(&V8${type}::info, $value${maybeOkParam})" } $implIncludes{"V8${type}.h"} = 1; @@ -2560,7 +2664,6 @@ sub JSValueToNative } } - sub GetV8HeaderName { my $type = shift; @@ -2568,17 +2671,17 @@ sub GetV8HeaderName return "EventListener.h" if $type eq "EventListener"; return "EventTarget.h" if $type eq "EventTarget"; return "SerializedScriptValue.h" if $type eq "SerializedScriptValue"; + return "ScriptValue.h" if $type eq "DOMObject"; return "V8${type}.h"; } - sub CreateCustomSignature { my $function = shift; my $count = @{$function->parameters}; my $name = $function->signature->name; - my $result = " const int ${name}_argc = ${count};\n" . - " v8::Handle<v8::FunctionTemplate> ${name}_argv[${name}_argc] = { "; + my $result = " const int ${name}Argc = ${count};\n" . + " v8::Handle<v8::FunctionTemplate> ${name}Argv[${name}Argc] = { "; my $first = 1; foreach my $parameter (@{$function->parameters}) { if ($first) { $first = 0; } @@ -2599,7 +2702,7 @@ sub CreateCustomSignature } } $result .= " };\n"; - $result .= " v8::Handle<v8::Signature> ${name}_signature = v8::Signature::New(desc, ${name}_argc, ${name}_argv);\n"; + $result .= " v8::Handle<v8::Signature> ${name}Signature = v8::Signature::New(desc, ${name}Argc, ${name}Argv);\n"; return $result; } @@ -2612,11 +2715,21 @@ sub RequiresCustomSignature $function->signature->extendedAttributes->{"V8Custom"}) { return 0; } + # No signature needed for overloaded function + if (@{$function->{overloads}} > 1) { + return 0; + } foreach my $parameter (@{$function->parameters}) { - if (IsWrapperType($parameter->type)) { - return 1; - } + if ($parameter->extendedAttributes->{"Optional"}) { + return 0; + } + } + + foreach my $parameter (@{$function->parameters}) { + if (IsWrapperType($parameter->type)) { + return 1; + } } return 0; } @@ -2625,6 +2738,8 @@ sub RequiresCustomSignature my %non_wrapper_types = ( 'float' => 1, 'double' => 1, + 'int' => 1, + 'unsigned int' => 1, 'short' => 1, 'unsigned short' => 1, 'long' => 1, @@ -2645,6 +2760,7 @@ my %non_wrapper_types = ( 'SVGPaintType' => 1, 'DOMTimeStamp' => 1, 'JSObject' => 1, + 'DOMObject' => 1, 'EventTarget' => 1, 'NodeFilter' => 1, 'EventListener' => 1 @@ -2704,8 +2820,9 @@ sub ReturnNativeToJSValue return "return v8::Integer::New($value)" if $nativeType eq "int"; return "return v8::Integer::NewFromUnsigned($value)" if $nativeType eq "unsigned"; - return "return v8DateOrNull($value);" if $type eq "Date"; + return "return v8DateOrNull($value)" if $type eq "Date"; return "return v8::Number::New($value)" if $codeGenerator->IsPrimitiveType($type) or $type eq "SVGPaintType"; + return "return $value.v8Value()" if $nativeType eq "ScriptValue"; if ($codeGenerator->IsStringType($type)) { my $conv = $signature->extendedAttributes->{"ConvertNullStringTo"}; @@ -2775,7 +2892,11 @@ sub WriteData my $checkType = $implInclude; $checkType =~ s/\.h//; - print $IMPL "#include \"$implInclude\"\n" unless $codeGenerator->IsSVGAnimatedType($checkType); + if ($implInclude =~ /wtf/) { + print $IMPL "#include \<$implInclude\>\n"; + } else { + print $IMPL "#include \"$implInclude\"\n" unless $codeGenerator->IsSVGAnimatedType($checkType); + } } print $IMPL "\n"; @@ -2833,7 +2954,7 @@ sub GenerateSVGContextRetrieval my $srcObject = "imp"; if ($srcIsPodType) { - $srcObject = "imp_wrapper"; + $srcObject = "impWrapper"; } my $contextDecl; @@ -2882,6 +3003,15 @@ sub IsSVGListTypeNeedingSpecialHandling return 0; } +sub GetVisibleInterfaceName +{ + my $interfaceName = shift; + + return "DOMException" if $interfaceName eq "DOMCoreException"; + return "FormData" if $interfaceName eq "DOMFormData"; + return $interfaceName; +} + sub DebugPrint { my $output = shift; diff --git a/WebCore/bindings/scripts/IDLParser.pm b/WebCore/bindings/scripts/IDLParser.pm index b2577d2..7db7747 100644 --- a/WebCore/bindings/scripts/IDLParser.pm +++ b/WebCore/bindings/scripts/IDLParser.pm @@ -14,7 +14,7 @@ # Library General Public License for more details. # # You should have received a copy of the GNU Library General Public License -# aint with this library; see the file COPYING.LIB. If not, write to +# along with this library; see the file COPYING.LIB. If not, write to # the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, # Boston, MA 02110-1301, USA. # @@ -64,7 +64,14 @@ sub Parse $parentsOnly = shift; if (!$preprocessor) { - $preprocessor = "/usr/bin/gcc -E -P -x c++"; + require Config; + my $gccLocation = ""; + if (($Config::Config{'osname'}) =~ /solaris/i) { + $gccLocation = "/usr/sfw/bin/gcc"; + } else { + $gccLocation = "/usr/bin/gcc"; + } + $preprocessor = $gccLocation . " -E -P -x c++"; } if (!$defines) { diff --git a/WebCore/bindings/scripts/IDLStructure.pm b/WebCore/bindings/scripts/IDLStructure.pm index f5970b4..6224e54 100644 --- a/WebCore/bindings/scripts/IDLStructure.pm +++ b/WebCore/bindings/scripts/IDLStructure.pm @@ -14,7 +14,7 @@ # Library General Public License for more details. # # You should have received a copy of the GNU Library General Public License -# aint with this library; see the file COPYING.LIB. If not, write to +# along with this library; see the file COPYING.LIB. If not, write to # the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, # Boston, MA 02110-1301, USA. # diff --git a/WebCore/bindings/scripts/generate-bindings.pl b/WebCore/bindings/scripts/generate-bindings.pl index ad29dc5..44ed4d3 100755 --- a/WebCore/bindings/scripts/generate-bindings.pl +++ b/WebCore/bindings/scripts/generate-bindings.pl @@ -16,7 +16,7 @@ # Library General Public License for more details. # # You should have received a copy of the GNU Library General Public License -# aint with this library; see the file COPYING.LIB. If not, write to +# along with this library; see the file COPYING.LIB. If not, write to # the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, # Boston, MA 02110-1301, USA. # diff --git a/WebCore/bindings/scripts/gobject-generate-headers.pl b/WebCore/bindings/scripts/gobject-generate-headers.pl new file mode 100644 index 0000000..1017406 --- /dev/null +++ b/WebCore/bindings/scripts/gobject-generate-headers.pl @@ -0,0 +1,77 @@ +#!/usr/bin/perl -w +# +# Copyright (C) 2009 Adam Dingle <adam@yorba.org> +# +# This file is part of WebKit +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library 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 +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public License +# aint with this library; see the file COPYING.LIB. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# + +my $classlist = <STDIN>; +chomp($classlist); +my @classes = split / /, $classlist; +@classes = sort @classes; + +print <<EOF; +/* This file is part of the WebKit open source project. + This file has been generated by gobject-generate-headers.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +EOF + +my $outType = $ARGV[0]; +my $header; +if ($outType eq "defines") { + $header = "webkitdomdefines_h"; +} elsif ($outType eq "gdom") { + $header = "webkitdom_h"; +} else { + die "unknown output type"; +} + +print "#ifndef ${header}\n"; +print "#define ${header}\n"; +print "\n"; + +if ($outType eq "defines") { + foreach my $class (@classes) { + print "typedef struct _WebKitDOM${class} WebKitDOM${class};\n"; + print "typedef struct _WebKitDOM${class}Class WebKitDOM${class}Class;\n"; + print "\n"; + } +} elsif ($outType eq "gdom") { + foreach my $class (@classes) { + print "#include <webkit/WebKitDOM${class}.h>\n"; + } +} + +print "\n"; +print "#endif\n"; diff --git a/WebCore/bindings/v8/DOMData.cpp b/WebCore/bindings/v8/DOMData.cpp index 417426f..568fc2c 100644 --- a/WebCore/bindings/v8/DOMData.cpp +++ b/WebCore/bindings/v8/DOMData.cpp @@ -39,9 +39,7 @@ namespace WebCore { DOMData::DOMData() - : m_delayedProcessingScheduled(false) - , m_isMainThread(WTF::isMainThread()) - , m_owningThread(WTF::currentThread()) + : m_owningThread(WTF::currentThread()) { } @@ -58,72 +56,9 @@ DOMData* DOMData::getCurrent() return childThreadDOMData; } -void DOMData::ensureDeref(V8ClassIndex::V8WrapperType type, void* domObject) +void DOMData::derefObject(WrapperTypeInfo* type, void* domObject) { - if (m_owningThread == WTF::currentThread()) { - // No need to delay the work. We can deref right now. - derefObject(type, domObject); - return; - } - - // We need to do the deref on the correct thread. - m_delayedObjectMap.set(domObject, type); - - // Post a task to the owning thread in order to process the delayed queue. - // FIXME: For now, we can only post to main thread due to WTF task posting limitation. We will fix this when we work on nested worker. - if (!m_delayedProcessingScheduled) { - m_delayedProcessingScheduled = true; - if (isMainThread()) - WTF::callOnMainThread(&derefDelayedObjectsInCurrentThread, 0); - } -} - -void DOMData::derefObject(V8ClassIndex::V8WrapperType type, void* domObject) -{ - switch (type) { - case V8ClassIndex::NODE: - static_cast<Node*>(domObject)->deref(); - break; - -#define MakeCase(type, name) \ - case V8ClassIndex::type: static_cast<name*>(domObject)->deref(); break; - DOM_OBJECT_TYPES(MakeCase) // This includes both active and non-active. -#undef MakeCase - -#if ENABLE(SVG) -#define MakeCase(type, name) \ - case V8ClassIndex::type: static_cast<name*>(domObject)->deref(); break; - SVG_OBJECT_TYPES(MakeCase) // This also includes SVGElementInstance. -#undef MakeCase - -#define MakeCase(type, name) \ - case V8ClassIndex::type: \ - static_cast<V8SVGPODTypeWrapper<name>*>(domObject)->deref(); break; - SVG_POD_NATIVE_TYPES(MakeCase) -#undef MakeCase -#endif - - default: - ASSERT_NOT_REACHED(); - break; - } -} - -void DOMData::derefDelayedObjects() -{ - WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); - - m_delayedProcessingScheduled = false; - - for (DelayedObjectMap::iterator iter(m_delayedObjectMap.begin()); iter != m_delayedObjectMap.end(); ++iter) - derefObject(iter->second, iter->first); - - m_delayedObjectMap.clear(); -} - -void DOMData::derefDelayedObjectsInCurrentThread(void*) -{ - getCurrent()->derefDelayedObjects(); + type->derefObject(domObject); } } // namespace WebCore diff --git a/WebCore/bindings/v8/DOMData.h b/WebCore/bindings/v8/DOMData.h index 7fa9e7d..4d7331b 100644 --- a/WebCore/bindings/v8/DOMData.h +++ b/WebCore/bindings/v8/DOMData.h @@ -32,6 +32,7 @@ #define DOMData_h #include "DOMDataStore.h" +#include "V8DOMWrapper.h" namespace WebCore { @@ -53,62 +54,39 @@ namespace WebCore { template<typename T> static void handleWeakObject(DOMDataStore::DOMWrapperMapType, v8::Persistent<v8::Object>, T* domObject); - void forgetDelayedObject(void* object) { m_delayedObjectMap.take(object); } - - // This is to ensure that we will deref DOM objects from the owning thread, - // not the GC thread. The helper function will be scheduled by the GC - // thread to get called from the owning thread. - static void derefDelayedObjectsInCurrentThread(void*); - void derefDelayedObjects(); - template<typename T> static void removeObjectsFromWrapperMap(AbstractWeakReferenceMap<T, v8::Object>& domMap); ThreadIdentifier owningThread() const { return m_owningThread; } private: - typedef WTF::HashMap<void*, V8ClassIndex::V8WrapperType> DelayedObjectMap; - - void ensureDeref(V8ClassIndex::V8WrapperType type, void* domObject); - static void derefObject(V8ClassIndex::V8WrapperType type, void* domObject); + static void derefObject(WrapperTypeInfo* type, void* domObject); template<typename T> class WrapperMapObjectRemover : public WeakReferenceMap<T, v8::Object>::Visitor { public: virtual void visitDOMWrapper(T* domObject, v8::Persistent<v8::Object> v8Object) { - V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(v8Object); + WrapperTypeInfo* type = V8DOMWrapper::domWrapperType(v8Object); derefObject(type, domObject); v8Object.Dispose(); } }; - // Stores all the DOM objects that are delayed to be processed when the - // owning thread gains control. - DelayedObjectMap m_delayedObjectMap; - - // The flag to indicate if the task to do the delayed process has - // already been posted. - bool m_delayedProcessingScheduled; - - bool m_isMainThread; ThreadIdentifier m_owningThread; }; template<typename T> void DOMData::handleWeakObject(DOMDataStore::DOMWrapperMapType mapType, v8::Persistent<v8::Object> v8Object, T* domObject) { - ASSERT(WTF::isMainThread()); DOMDataList& list = DOMDataStore::allStores(); for (size_t i = 0; i < list.size(); ++i) { DOMDataStore* store = list[i]; + ASSERT(store->domData()->owningThread() == WTF::currentThread()); - DOMDataStore::InternalDOMWrapperMap<T>* domMap = static_cast<DOMDataStore::InternalDOMWrapperMap<T>*>(store->getDOMWrapperMap(mapType)); - - if (domMap->removeIfPresent(domObject, v8Object)) { - ASSERT(store->domData()->owningThread() == WTF::currentThread()); + DOMWrapperMap<T>* domMap = static_cast<DOMWrapperMap<T>*>(store->getDOMWrapperMap(mapType)); + if (domMap->removeIfPresent(domObject, v8Object)) store->domData()->derefObject(V8DOMWrapper::domWrapperType(v8Object), domObject); - } } } diff --git a/WebCore/bindings/v8/DOMDataStore.cpp b/WebCore/bindings/v8/DOMDataStore.cpp index e181ebc..5d609d8 100644 --- a/WebCore/bindings/v8/DOMDataStore.cpp +++ b/WebCore/bindings/v8/DOMDataStore.cpp @@ -114,11 +114,6 @@ WTF::Mutex& DOMDataStore::allStoresMutex() return staticDOMDataListMutex; } -void DOMDataStore::forgetDelayedObject(DOMData* domData, void* object) -{ - domData->forgetDelayedObject(object); -} - void* DOMDataStore::getDOMWrapperMap(DOMWrapperMapType type) { switch (type) { diff --git a/WebCore/bindings/v8/DOMDataStore.h b/WebCore/bindings/v8/DOMDataStore.h index 54a49e7..c39a0ed 100644 --- a/WebCore/bindings/v8/DOMDataStore.h +++ b/WebCore/bindings/v8/DOMDataStore.h @@ -31,7 +31,7 @@ #ifndef DOMDataStore_h #define DOMDataStore_h -#include "DOMObjectsInclude.h" +#include "V8DOMMap.h" #include "V8Node.h" #include <v8.h> @@ -47,6 +47,7 @@ namespace WebCore { class DOMData; + class DOMDataStore; typedef WTF::Vector<DOMDataStore*> DOMDataList; @@ -160,22 +161,6 @@ namespace WebCore { #endif }; - template <class KeyType> - class InternalDOMWrapperMap : public DOMWrapperMap<KeyType> { - public: - InternalDOMWrapperMap(DOMData* domData, v8::WeakReferenceCallback callback) - : DOMWrapperMap<KeyType>(callback), m_domData(domData) { } - - virtual void forget(KeyType* object) - { - DOMWrapperMap<KeyType>::forget(object); - forgetDelayedObject(m_domData, object); - } - - private: - DOMData* m_domData; - }; - class IntrusiveDOMWrapperMap : public AbstractWeakReferenceMap<Node, v8::Object> { public: IntrusiveDOMWrapperMap(v8::WeakReferenceCallback callback) @@ -252,25 +237,21 @@ namespace WebCore { DOMDataStore(DOMData*); virtual ~DOMDataStore(); - // A list of all DOMDataStore objects. Traversed during GC to find a thread-specific map that - // contains the object - so we can schedule the object to be deleted on the thread which created it. + // A list of all DOMDataStore objects in the current V8 instance (thread). Normally, each World has a DOMDataStore. static DOMDataList& allStores(); // Mutex to protect against concurrent access of DOMDataList. static WTF::Mutex& allStoresMutex(); - // Helper function to avoid circular includes. - static void forgetDelayedObject(DOMData*, void* object); - DOMData* domData() const { return m_domData; } void* getDOMWrapperMap(DOMWrapperMapType); DOMNodeMapping& domNodeMap() { return *m_domNodeMap; } - InternalDOMWrapperMap<void>& domObjectMap() { return *m_domObjectMap; } - InternalDOMWrapperMap<void>& activeDomObjectMap() { return *m_activeDomObjectMap; } + DOMWrapperMap<void>& domObjectMap() { return *m_domObjectMap; } + DOMWrapperMap<void>& activeDomObjectMap() { return *m_activeDomObjectMap; } #if ENABLE(SVG) - InternalDOMWrapperMap<SVGElementInstance>& domSvgElementInstanceMap() { return *m_domSvgElementInstanceMap; } - InternalDOMWrapperMap<void>& domSvgObjectWithContextMap() { return *m_domSvgObjectWithContextMap; } + DOMWrapperMap<SVGElementInstance>& domSvgElementInstanceMap() { return *m_domSvgElementInstanceMap; } + DOMWrapperMap<void>& domSvgObjectWithContextMap() { return *m_domSvgObjectWithContextMap; } #endif // Need by V8GCController. @@ -286,11 +267,11 @@ namespace WebCore { #endif DOMNodeMapping* m_domNodeMap; - InternalDOMWrapperMap<void>* m_domObjectMap; - InternalDOMWrapperMap<void>* m_activeDomObjectMap; + DOMWrapperMap<void>* m_domObjectMap; + DOMWrapperMap<void>* m_activeDomObjectMap; #if ENABLE(SVG) - InternalDOMWrapperMap<SVGElementInstance>* m_domSvgElementInstanceMap; - InternalDOMWrapperMap<void>* m_domSvgObjectWithContextMap; + DOMWrapperMap<SVGElementInstance>* m_domSvgElementInstanceMap; + DOMWrapperMap<void>* m_domSvgObjectWithContextMap; #endif private: diff --git a/WebCore/bindings/v8/DOMWrapperWorld.h b/WebCore/bindings/v8/DOMWrapperWorld.h index f54cd4e..2a9df30 100644 --- a/WebCore/bindings/v8/DOMWrapperWorld.h +++ b/WebCore/bindings/v8/DOMWrapperWorld.h @@ -43,6 +43,7 @@ namespace WebCore { class DOMWrapperWorld : public RefCounted<DOMWrapperWorld> { public: static PassRefPtr<DOMWrapperWorld> create() { return adoptRef(new DOMWrapperWorld()); } + virtual ~DOMWrapperWorld() {} protected: DOMWrapperWorld(); diff --git a/WebCore/bindings/v8/DateExtension.cpp b/WebCore/bindings/v8/DateExtension.cpp index abf8967..f2b6242 100644 --- a/WebCore/bindings/v8/DateExtension.cpp +++ b/WebCore/bindings/v8/DateExtension.cpp @@ -88,7 +88,7 @@ void DateExtension::setAllowSleep(bool allow) return; v8::Handle<v8::Value> argv[1]; - argv[0] = v8::String::New(allow ? "false" : "true"); + argv[0] = v8::Boolean::New(!allow); v8::Handle<v8::Function>::Cast(sleepFunctionHandle)->Call(v8::Object::New(), 1, argv); } diff --git a/WebCore/bindings/v8/JavaScriptCallFrame.cpp b/WebCore/bindings/v8/JavaScriptCallFrame.cpp new file mode 100644 index 0000000..049321b --- /dev/null +++ b/WebCore/bindings/v8/JavaScriptCallFrame.cpp @@ -0,0 +1,120 @@ +/* + * 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 "JavaScriptCallFrame.h" + +#if ENABLE(JAVASCRIPT_DEBUGGER) + +#include "V8Binding.h" + +namespace WebCore { + +JavaScriptCallFrame::JavaScriptCallFrame(v8::Handle<v8::Context> debuggerContext, v8::Handle<v8::Object> callFrame) + : m_debuggerContext(debuggerContext) + , m_callFrame(callFrame) +{ +} + +JavaScriptCallFrame::~JavaScriptCallFrame() +{ +} + +JavaScriptCallFrame* JavaScriptCallFrame::caller() +{ + if (!m_caller) { + v8::HandleScope handleScope; + v8::Context::Scope contextScope(m_debuggerContext.get()); + v8::Handle<v8::Value> callerFrame = m_callFrame.get()->Get(v8String("caller")); + if (!callerFrame->IsObject()) + return 0; + m_caller = JavaScriptCallFrame::create(m_debuggerContext.get(), v8::Handle<v8::Object>::Cast(callerFrame)); + } + return m_caller.get(); +} + +int JavaScriptCallFrame::sourceID() const +{ + v8::HandleScope handleScope; + v8::Context::Scope contextScope(m_debuggerContext.get()); + v8::Handle<v8::Value> result = m_callFrame.get()->Get(v8String("sourceID")); + if (result->IsInt32()) + return result->Int32Value(); + return 0; +} + +int JavaScriptCallFrame::line() const +{ + v8::HandleScope handleScope; + v8::Context::Scope contextScope(m_debuggerContext.get()); + v8::Handle<v8::Value> result = m_callFrame.get()->Get(v8String("line")); + if (result->IsInt32()) + return result->Int32Value(); + return 0; +} + +String JavaScriptCallFrame::functionName() const +{ + v8::HandleScope handleScope; + v8::Context::Scope contextScope(m_debuggerContext.get()); + v8::Handle<v8::Value> result = m_callFrame.get()->Get(v8String("functionName")); + return toWebCoreString(result); +} + +v8::Handle<v8::Value> JavaScriptCallFrame::scopeChain() const +{ + v8::Handle<v8::Array> scopeChain = v8::Handle<v8::Array>::Cast(m_callFrame.get()->Get(v8String("scopeChain"))); + v8::Handle<v8::Array> result = v8::Array::New(scopeChain->Length()); + for (uint32_t i = 0; i < scopeChain->Length(); i++) + result->Set(i, scopeChain->Get(i)); + return result; +} + +int JavaScriptCallFrame::scopeType(int scopeIndex) const +{ + v8::Handle<v8::Array> scopeType = v8::Handle<v8::Array>::Cast(m_callFrame.get()->Get(v8String("scopeType"))); + return scopeType->Get(scopeIndex)->Int32Value(); +} + +v8::Handle<v8::Value> JavaScriptCallFrame::thisObject() const +{ + return m_callFrame.get()->Get(v8String("thisObject")); +} + +v8::Handle<v8::Value> JavaScriptCallFrame::evaluate(const String& expression) +{ + v8::Handle<v8::Function> evalFunction = v8::Handle<v8::Function>::Cast(m_callFrame.get()->Get(v8String("evaluate"))); + v8::Handle<v8::Value> argv[] = { v8String(expression) }; + return evalFunction->Call(m_callFrame.get(), 1, argv); +} + +} // namespace WebCore + +#endif // ENABLE(JAVASCRIPT_DEBUGGER) diff --git a/WebCore/bindings/v8/JavaScriptCallFrame.h b/WebCore/bindings/v8/JavaScriptCallFrame.h new file mode 100644 index 0000000..95a0510 --- /dev/null +++ b/WebCore/bindings/v8/JavaScriptCallFrame.h @@ -0,0 +1,74 @@ +/* + * 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 JavaScriptCallFrame_h +#define JavaScriptCallFrame_h + +#if ENABLE(JAVASCRIPT_DEBUGGER) + +#include "OwnHandle.h" +#include "PlatformString.h" +#include <v8-debug.h> + +namespace WebCore { + +class JavaScriptCallFrame : public RefCounted<JavaScriptCallFrame> { +public: + static PassRefPtr<JavaScriptCallFrame> create(v8::Handle<v8::Context> debuggerContext, v8::Handle<v8::Object> callFrame) + { + return adoptRef(new JavaScriptCallFrame(debuggerContext, callFrame)); + } + ~JavaScriptCallFrame(); + + JavaScriptCallFrame* caller(); + + int sourceID() const; + int line() const; + String functionName() const; + + v8::Handle<v8::Value> scopeChain() const; + int scopeType(int scopeIndex) const; + v8::Handle<v8::Value> thisObject() const; + + v8::Handle<v8::Value> evaluate(const String& expression); + +private: + JavaScriptCallFrame(v8::Handle<v8::Context> debuggerContext, v8::Handle<v8::Object> callFrame); + + RefPtr<JavaScriptCallFrame> m_caller; + OwnHandle<v8::Context> m_debuggerContext; + OwnHandle<v8::Object> m_callFrame; +}; + +} // namespace WebCore + +#endif // ENABLE(JAVASCRIPT_DEBUGGER) + +#endif // JavaScriptCallFrame_h diff --git a/WebCore/bindings/v8/NPV8Object.cpp b/WebCore/bindings/v8/NPV8Object.cpp index 06243d4..56f9810 100644 --- a/WebCore/bindings/v8/NPV8Object.cpp +++ b/WebCore/bindings/v8/NPV8Object.cpp @@ -36,9 +36,9 @@ #include "ScriptController.h" #include "V8GCController.h" #include "V8Helpers.h" -#include "V8Index.h" #include "V8NPUtils.h" #include "V8Proxy.h" +#include "WrapperTypeInfo.h" #include "npruntime_impl.h" #include "npruntime_priv.h" @@ -55,10 +55,20 @@ using WebCore::npObjectInternalFieldCount; using WebCore::toV8Context; using WebCore::toV8Proxy; -using WebCore::V8ClassIndex; using WebCore::V8DOMWrapper; using WebCore::V8GCController; using WebCore::V8Proxy; +using WebCore::WrapperTypeInfo; + +namespace WebCore { + +WrapperTypeInfo* npObjectTypeInfo() +{ + static WrapperTypeInfo typeInfo = { 0, 0, false }; + return &typeInfo; +} + +} // FIXME: Comments on why use malloc and free. static NPObject* allocV8NPObject(NPP, NPClass*) @@ -115,8 +125,8 @@ NPObject* npCreateV8ScriptObject(NPP npp, v8::Handle<v8::Object> object, WebCore { // Check to see if this object is already wrapped. if (object->InternalFieldCount() == npObjectInternalFieldCount) { - v8::Local<v8::Value> typeIndex = object->GetInternalField(WebCore::v8DOMWrapperTypeIndex); - if (typeIndex->IsNumber() && typeIndex->Uint32Value() == V8ClassIndex::NPOBJECT) { + WrapperTypeInfo* typeInfo = static_cast<WrapperTypeInfo*>(object->GetPointerFromInternalField(WebCore::v8DOMWrapperTypeIndex)); + if (typeInfo == WebCore::npObjectTypeInfo()) { NPObject* returnValue = v8ObjectToNPObject(object); _NPN_RetainObject(returnValue); @@ -299,6 +309,9 @@ bool _NPN_GetProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName, NP v8::Handle<v8::Object> obj(object->v8Object); v8::Local<v8::Value> v8result = obj->Get(npIdentifierToV8Identifier(propertyName)); + + if (v8result.IsEmpty()) + return false; convertV8ObjectToNPVariant(v8result, npObject, result); return true; diff --git a/WebCore/bindings/v8/NPV8Object.h b/WebCore/bindings/v8/NPV8Object.h index e5550ee..b6fecce 100644 --- a/WebCore/bindings/v8/NPV8Object.h +++ b/WebCore/bindings/v8/NPV8Object.h @@ -30,7 +30,7 @@ #ifndef NPV8Object_h #define NPV8Object_h -#include "V8Index.h" +#include "V8DOMWrapper.h" #if PLATFORM(CHROMIUM) // FIXME: Chromium uses a different npruntime.h, which is in @@ -48,6 +48,8 @@ namespace WebCore { class DOMWindow; static const int npObjectInternalFieldCount = v8DefaultWrapperInternalFieldCount + 0; + + WrapperTypeInfo* npObjectTypeInfo(); } extern NPClass* npScriptObjectClass; diff --git a/WebCore/bindings/v8/ScopedDOMDataStore.cpp b/WebCore/bindings/v8/ScopedDOMDataStore.cpp index 19cd545..df4a63a 100644 --- a/WebCore/bindings/v8/ScopedDOMDataStore.cpp +++ b/WebCore/bindings/v8/ScopedDOMDataStore.cpp @@ -36,12 +36,12 @@ namespace WebCore { ScopedDOMDataStore::ScopedDOMDataStore(DOMData* domData) : DOMDataStore(domData) { - m_domNodeMap = new InternalDOMWrapperMap<Node>(domData, &DOMDataStore::weakNodeCallback); - m_domObjectMap = new InternalDOMWrapperMap<void>(domData, &DOMDataStore::weakDOMObjectCallback); - m_activeDomObjectMap = new InternalDOMWrapperMap<void>(domData, &DOMDataStore::weakActiveDOMObjectCallback); + m_domNodeMap = new DOMWrapperMap<Node>(&DOMDataStore::weakNodeCallback); + m_domObjectMap = new DOMWrapperMap<void>(&DOMDataStore::weakDOMObjectCallback); + m_activeDomObjectMap = new DOMWrapperMap<void>(&DOMDataStore::weakActiveDOMObjectCallback); #if ENABLE(SVG) - m_domSvgElementInstanceMap = new InternalDOMWrapperMap<SVGElementInstance>(domData, &DOMDataStore::weakSVGElementInstanceCallback); - m_domSvgObjectWithContextMap = new InternalDOMWrapperMap<void>(domData, &DOMDataStore::weakSVGObjectWithContextCallback); + m_domSvgElementInstanceMap = new DOMWrapperMap<SVGElementInstance>(&DOMDataStore::weakSVGElementInstanceCallback); + m_domSvgObjectWithContextMap = new DOMWrapperMap<void>(&DOMDataStore::weakSVGObjectWithContextCallback); #endif } diff --git a/WebCore/bindings/v8/ScriptCallStack.cpp b/WebCore/bindings/v8/ScriptCallStack.cpp index 21063ed..45e7205 100644 --- a/WebCore/bindings/v8/ScriptCallStack.cpp +++ b/WebCore/bindings/v8/ScriptCallStack.cpp @@ -32,29 +32,33 @@ #include "ScriptCallStack.h" #include "ScriptController.h" +#include "ScriptDebugServer.h" #include <v8.h> #include "V8Binding.h" -#include "V8Proxy.h" namespace WebCore { ScriptCallStack* ScriptCallStack::create(const v8::Arguments& arguments, unsigned skipArgumentCount) { String sourceName; int sourceLineNumber; - if (!V8Proxy::sourceName(sourceName)) { - return 0; - } - if (!V8Proxy::sourceLineNumber(sourceLineNumber)) { - return 0; - } - sourceLineNumber += 1; - return new ScriptCallStack(arguments, skipArgumentCount, sourceName, sourceLineNumber); + String funcName; + if (!callLocation(&sourceName, &sourceLineNumber, &funcName)) + return 0; + return new ScriptCallStack(arguments, skipArgumentCount, sourceName, sourceLineNumber, funcName); } -ScriptCallStack::ScriptCallStack(const v8::Arguments& arguments, unsigned skipArgumentCount, String sourceName, int sourceLineNumber) - : m_lastCaller(String(), sourceName, sourceLineNumber, arguments, skipArgumentCount) +bool ScriptCallStack::callLocation(String* sourceName, int* sourceLineNumber, String* functionName) +{ + if (!ScriptDebugServer::topStackFrame(*sourceName, *sourceLineNumber, *functionName)) + return false; + *sourceLineNumber += 1; + return true; +} + +ScriptCallStack::ScriptCallStack(const v8::Arguments& arguments, unsigned skipArgumentCount, String sourceName, int sourceLineNumber, String functionName) + : m_lastCaller(functionName, sourceName, sourceLineNumber, arguments, skipArgumentCount) , m_scriptState(ScriptState::current()) { } diff --git a/WebCore/bindings/v8/ScriptCallStack.h b/WebCore/bindings/v8/ScriptCallStack.h index 8ac394c..2433bde 100644 --- a/WebCore/bindings/v8/ScriptCallStack.h +++ b/WebCore/bindings/v8/ScriptCallStack.h @@ -47,6 +47,8 @@ namespace WebCore { static ScriptCallStack* create(const v8::Arguments&, unsigned skipArgumentCount = 0); ~ScriptCallStack(); + static bool callLocation(String* sourceName, int* sourceLineNumber, String* functionName); + const ScriptCallFrame& at(unsigned) const; // FIXME: implement retrieving and storing call stack trace unsigned size() const { return 1; } @@ -55,7 +57,7 @@ namespace WebCore { ScriptState* globalState() const { return m_scriptState; } private: - ScriptCallStack(const v8::Arguments& arguments, unsigned skipArgumentCount, String sourceName, int sourceLineNumber); + ScriptCallStack(const v8::Arguments& arguments, unsigned skipArgumentCount, String sourceName, int sourceLineNumber, String funcName); ScriptCallFrame m_lastCaller; ScriptState* m_scriptState; diff --git a/WebCore/bindings/v8/ScriptController.cpp b/WebCore/bindings/v8/ScriptController.cpp index 40a71be..ee15eaa 100644 --- a/WebCore/bindings/v8/ScriptController.cpp +++ b/WebCore/bindings/v8/ScriptController.cpp @@ -33,7 +33,6 @@ #include "ScriptController.h" #include "PlatformBridge.h" -#include "CString.h" #include "Document.h" #include "DOMWindow.h" #include "Event.h" @@ -48,6 +47,7 @@ #include "NPV8Object.h" #include "ScriptSourceCode.h" #include "Settings.h" +#include "UserGestureIndicator.h" #include "V8Binding.h" #include "V8BindingState.h" #include "V8DOMWindow.h" @@ -59,6 +59,7 @@ #include "Widget.h" #include "XSSAuditor.h" #include <wtf/StdLibExtras.h> +#include <wtf/text/CString.h> namespace WebCore { @@ -153,9 +154,10 @@ void ScriptController::updatePlatformScriptObjects() bool ScriptController::processingUserGesture(DOMWrapperWorld*) const { Frame* activeFrame = V8Proxy::retrieveFrameForEnteredContext(); - // No script is running, so it must be run by users. + // No script is running, so it is user-initiated unless the gesture stack + // explicitly says it is not. if (!activeFrame) - return true; + return UserGestureIndicator::processingUserGesture(); V8Proxy* activeProxy = activeFrame->script()->proxy(); @@ -176,7 +178,7 @@ bool ScriptController::processingUserGesture(DOMWrapperWorld*) const // Based on code from kjs_bindings.cpp. // Note: This is more liberal than Firefox's implementation. if (event) { - if (event->createdByDOM()) + if (!UserGestureIndicator::processingUserGesture()) return false; const AtomicString& type = event->type(); @@ -190,7 +192,7 @@ bool ScriptController::processingUserGesture(DOMWrapperWorld*) const if (eventOk) return true; - } else if (activeProxy->inlineCode() && !activeProxy->timerCallback()) { + } else if (m_sourceURL && m_sourceURL->isNull() && !activeProxy->timerCallback()) { // This is the <a href="javascript:window.open('...')> case -> we let it through. return true; } @@ -219,7 +221,9 @@ void ScriptController::evaluateInIsolatedWorld(unsigned worldID, const Vector<Sc ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode) { String sourceURL = sourceCode.url(); - + const String* savedSourceURL = m_sourceURL; + m_sourceURL = &sourceURL; + if (!m_XSSAuditor->canEvaluate(sourceCode.source())) { // This script is not safe to be evaluated. return ScriptValue(); @@ -237,9 +241,11 @@ ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode) v8::Local<v8::Value> object = m_proxy->evaluate(sourceCode, 0); // Evaluating the JavaScript could cause the frame to be deallocated - // so we starot the keep alive timer here. + // so we start the keep alive timer here. m_frame->keepAlive(); + m_sourceURL = savedSourceURL; + if (object.IsEmpty() || object->IsUndefined()) return ScriptValue(); @@ -402,7 +408,7 @@ NPObject* ScriptController::windowScriptNPObject() if (m_windowScriptNPObject) return 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. m_windowScriptNPObject = createScriptObject(m_frame); @@ -419,7 +425,7 @@ NPObject* ScriptController::windowScriptNPObject() NPObject* ScriptController::createScriptObjectForPluginElement(HTMLPlugInElement* plugin) { // Can't create NPObjects when JavaScript is disabled. - if (!canExecuteScripts()) + if (!canExecuteScripts(NotAboutToExecuteScript)) return createNoScriptObject(); v8::HandleScope handleScope; diff --git a/WebCore/bindings/v8/ScriptController.h b/WebCore/bindings/v8/ScriptController.h index b3995b2..7e13740 100644 --- a/WebCore/bindings/v8/ScriptController.h +++ b/WebCore/bindings/v8/ScriptController.h @@ -55,6 +55,11 @@ class String; class Widget; class XSSAuditor; +enum ReasonForCallingCanExecuteScripts { + AboutToExecuteScript, + NotAboutToExecuteScript +}; + class ScriptController { public: ScriptController(Frame*); @@ -113,7 +118,7 @@ public: // Check if the javascript engine has been initialized. bool haveInterpreter() const; - bool canExecuteScripts(); + bool canExecuteScripts(ReasonForCallingCanExecuteScripts); // FIXME: void* is a compile hack. void attachDebugger(void*); diff --git a/WebCore/bindings/v8/ScriptDebugServer.cpp b/WebCore/bindings/v8/ScriptDebugServer.cpp index 3fe8c34..54d7694 100644 --- a/WebCore/bindings/v8/ScriptDebugServer.cpp +++ b/WebCore/bindings/v8/ScriptDebugServer.cpp @@ -29,17 +29,379 @@ */ #include "config.h" - #include "ScriptDebugServer.h" +#if ENABLE(JAVASCRIPT_DEBUGGER) + +#include "Frame.h" +#include "JavaScriptCallFrame.h" +#include "Page.h" +#include "ScriptDebugListener.h" +#include "V8Binding.h" +#include "V8DOMWindow.h" +#include "V8Proxy.h" +#include <wtf/StdLibExtras.h> + namespace WebCore { -void ScriptDebugServer::recompileAllJSFunctions() +v8::Persistent<v8::Context> ScriptDebugServer::s_utilityContext; + +ScriptDebugServer::MessageLoopDispatchHandler ScriptDebugServer::s_messageLoopDispatchHandler = 0; + +ScriptDebugServer& ScriptDebugServer::shared() +{ + DEFINE_STATIC_LOCAL(ScriptDebugServer, server, ()); + return server; +} + +ScriptDebugServer::ScriptDebugServer() + : m_pauseOnExceptionsState(DontPauseOnExceptions) + , m_currentCallFrameState(0) +{ +} + +void ScriptDebugServer::setDebuggerScriptSource(const String& scriptSource) +{ + m_debuggerScriptSource = scriptSource; +} + +void ScriptDebugServer::addListener(ScriptDebugListener* listener, Page* page) +{ +#if ENABLE(V8_SCRIPT_DEBUG_SERVER) + v8::HandleScope scope; + v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); + v8::Context::Scope contextScope(debuggerContext); + + if (!m_listenersMap.size()) { + ensureDebuggerScriptCompiled(); + ASSERT(!m_debuggerScript.get()->IsUndefined()); + v8::Debug::SetMessageHandler2(&ScriptDebugServer::onV8DebugMessage); + v8::Debug::SetHostDispatchHandler(&ScriptDebugServer::onV8DebugHostDispatch, 100 /* ms */); + } + m_listenersMap.set(page, listener); + V8Proxy* proxy = V8Proxy::retrieve(page->mainFrame()); + v8::Local<v8::Context> context = proxy->mainWorldContext(); + String contextData = toWebCoreStringWithNullCheck(context->GetData()); + m_contextDataMap.set(listener, contextData); + + v8::Handle<v8::Function> getScriptsFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("getScripts"))); + v8::Handle<v8::Value> value = v8::Debug::Call(getScriptsFunction); + if (value.IsEmpty()) + return; + ASSERT(!value->IsUndefined() && value->IsArray()); + v8::Handle<v8::Array> scriptsArray = v8::Handle<v8::Array>::Cast(value); + for (unsigned i = 0; i < scriptsArray->Length(); ++i) + dispatchDidParseSource(listener, v8::Handle<v8::Object>::Cast(scriptsArray->Get(v8::Integer::New(i)))); +#endif +} + +void ScriptDebugServer::removeListener(ScriptDebugListener* listener, Page* page) +{ + if (!m_listenersMap.contains(page)) + return; + + m_listenersMap.remove(page); + + if (m_listenersMap.isEmpty()) { + v8::Debug::SetMessageHandler2(0); + v8::Debug::SetHostDispatchHandler(0); + } + // FIXME: Remove all breakpoints set by the agent. + // FIXME: Force continue if detach happened in nessted message loop while + // debugger was paused on a breakpoint(as long as there are other + // attached agents v8 will wait for explicit'continue' message). + // FIXME: send continue command to v8 if necessary; +} + +void ScriptDebugServer::setBreakpoint(const String& sourceID, unsigned lineNumber, ScriptBreakpoint breakpoint) +{ +#if ENABLE(V8_SCRIPT_DEBUG_SERVER) + v8::HandleScope scope; + v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); + v8::Context::Scope contextScope(debuggerContext); + + v8::Local<v8::Object> args = v8::Object::New(); + args->Set(v8::String::New("scriptId"), v8String(sourceID)); + args->Set(v8::String::New("lineNumber"), v8::Integer::New(lineNumber)); + args->Set(v8::String::New("condition"), v8String(breakpoint.condition)); + args->Set(v8::String::New("enabled"), v8::Boolean::New(breakpoint.enabled)); + + v8::Handle<v8::Function> setBreakpointFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("setBreakpoint"))); + v8::Debug::Call(setBreakpointFunction, args); +#endif +} + +void ScriptDebugServer::removeBreakpoint(const String& sourceID, unsigned lineNumber) +{ +#if ENABLE(V8_SCRIPT_DEBUG_SERVER) + v8::HandleScope scope; + v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); + v8::Context::Scope contextScope(debuggerContext); + + v8::Local<v8::Object> args = v8::Object::New(); + args->Set(v8::String::New("scriptId"), v8String(sourceID)); + args->Set(v8::String::New("lineNumber"), v8::Integer::New(lineNumber)); + + v8::Handle<v8::Function> removeBreakpointFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("removeBreakpoint"))); + v8::Debug::Call(removeBreakpointFunction, args); +#endif +} + +void ScriptDebugServer::clearBreakpoints() +{ +#if ENABLE(V8_SCRIPT_DEBUG_SERVER) + ensureDebuggerScriptCompiled(); + v8::HandleScope scope; + v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); + v8::Context::Scope contextScope(debuggerContext); + + v8::Handle<v8::Function> setBreakpointsActivated = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("clearBreakpoints"))); + v8::Debug::Call(setBreakpointsActivated); +#endif +} + +void ScriptDebugServer::setBreakpointsActivated(bool enabled) +{ +#if ENABLE(V8_SCRIPT_DEBUG_SERVER) + ensureDebuggerScriptCompiled(); + v8::HandleScope scope; + v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); + v8::Context::Scope contextScope(debuggerContext); + + v8::Local<v8::Object> args = v8::Object::New(); + args->Set(v8::String::New("enabled"), v8::Boolean::New(enabled)); + v8::Handle<v8::Function> setBreakpointsActivated = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("setBreakpointsActivated"))); + v8::Debug::Call(setBreakpointsActivated, args); +#endif +} + +void ScriptDebugServer::continueProgram() +{ +#if ENABLE(V8_SCRIPT_DEBUG_SERVER) + String cmd("{\"seq\":1,\"type\":\"request\",\"command\":\"continue\"}"); + v8::Debug::SendCommand(reinterpret_cast<const uint16_t*>(cmd.characters()), cmd.length(), new v8::Debug::ClientData()); + didResume(); +#endif +} + +void ScriptDebugServer::stepIntoStatement() +{ +#if ENABLE(V8_SCRIPT_DEBUG_SERVER) + String cmd("{\"seq\":1,\"type\":\"request\",\"command\":\"continue\",\"arguments\":{\"stepaction\":\"in\"}}"); + v8::Debug::SendCommand(reinterpret_cast<const uint16_t*>(cmd.characters()), cmd.length(), new v8::Debug::ClientData()); + didResume(); +#endif +} + +void ScriptDebugServer::stepOverStatement() { +#if ENABLE(V8_SCRIPT_DEBUG_SERVER) + String cmd("{\"seq\":1,\"type\":\"request\",\"command\":\"continue\",\"arguments\":{\"stepaction\":\"next\"}}"); + v8::Debug::SendCommand(reinterpret_cast<const uint16_t*>(cmd.characters()), cmd.length(), new v8::Debug::ClientData()); + didResume(); +#endif } -void ScriptDebugServer::recompileAllJSFunctionsSoon() +void ScriptDebugServer::stepOutOfFunction() { +#if ENABLE(V8_SCRIPT_DEBUG_SERVER) + String cmd("{\"seq\":1,\"type\":\"request\",\"command\":\"continue\",\"arguments\":{\"stepaction\":\"out\"}}"); + v8::Debug::SendCommand(reinterpret_cast<const uint16_t*>(cmd.characters()), cmd.length(), new v8::Debug::ClientData()); + didResume(); +#endif +} + +ScriptState* ScriptDebugServer::currentCallFrameState() +{ + return m_currentCallFrameState; +} + +v8::Handle<v8::Value> ScriptDebugServer::currentCallFrameV8() +{ +#if ENABLE(V8_SCRIPT_DEBUG_SERVER) + if (!m_currentCallFrame.get().IsEmpty()) + return m_currentCallFrame.get(); + + // Check on a bp. + v8::Handle<v8::Function> currentCallFrameFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("currentCallFrame"))); + v8::Handle<v8::Value> argv[] = { m_executionState.get() }; + v8::Handle<v8::Value> result = currentCallFrameFunction->Call(m_debuggerScript.get(), 1, argv); + m_currentCallFrame.set(result); + return result; +#else + return v8::Handle<v8::Value>(); +#endif +} + +PassRefPtr<JavaScriptCallFrame> ScriptDebugServer::currentCallFrame() +{ + return JavaScriptCallFrame::create(v8::Debug::GetDebugContext(), v8::Handle<v8::Object>::Cast(currentCallFrameV8())); +} + +void ScriptDebugServer::onV8DebugMessage(const v8::Debug::Message& message) +{ + ScriptDebugServer::shared().handleV8DebugMessage(message); +} + +void ScriptDebugServer::onV8DebugHostDispatch() +{ + ScriptDebugServer::shared().handleV8DebugHostDispatch(); +} + +void ScriptDebugServer::handleV8DebugHostDispatch() +{ + if (!s_messageLoopDispatchHandler) + return; + + Vector<WebCore::Page*> pages; + for (ListenersMap::iterator it = m_listenersMap.begin(); it != m_listenersMap.end(); ++it) + pages.append(it->first); + + s_messageLoopDispatchHandler(pages); +} + +void ScriptDebugServer::handleV8DebugMessage(const v8::Debug::Message& message) +{ + v8::HandleScope scope; + + if (!message.IsEvent()) + return; + + // Ignore unsupported event types. + if (message.GetEvent() != v8::AfterCompile && message.GetEvent() != v8::Break) + return; + + v8::Handle<v8::Context> context = message.GetEventContext(); + // If the context is from one of the inpected tabs it should have its context + // data. Skip events from unknown contexts. + if (context.IsEmpty()) + return; + + // Test that context has associated global dom window object. + v8::Handle<v8::Object> global = context->Global(); + if (global.IsEmpty()) + return; + + global = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), global); + if (global.IsEmpty()) + return; + + Frame* frame = V8Proxy::retrieveFrame(context); + if (frame) { + ScriptDebugListener* listener = m_listenersMap.get(frame->page()); + if (listener) { + if (message.GetEvent() == v8::AfterCompile) { + v8::Context::Scope contextScope(v8::Debug::GetDebugContext()); + v8::Local<v8::Object> args = v8::Object::New(); + args->Set(v8::String::New("eventData"), message.GetEventData()); + v8::Handle<v8::Function> onAfterCompileFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("getAfterCompileScript"))); + v8::Handle<v8::Value> argv[] = { message.GetExecutionState(), args }; + v8::Handle<v8::Value> value = onAfterCompileFunction->Call(m_debuggerScript.get(), 2, argv); + ASSERT(value->IsObject()); + v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); + dispatchDidParseSource(listener, object); + } else if (message.GetEvent() == v8::Break) { + m_executionState.set(message.GetExecutionState()); + m_currentCallFrameState = mainWorldScriptState(frame); + listener->didPause(); + m_currentCallFrameState = 0; + } + } + } +} + +void ScriptDebugServer::dispatchDidParseSource(ScriptDebugListener* listener, v8::Handle<v8::Object> object) +{ + String contextData = toWebCoreStringWithNullCheck(object->Get(v8::String::New("contextData"))); + if (contextData != m_contextDataMap.get(listener)) + return; + + listener->didParseSource( + toWebCoreStringWithNullCheck(object->Get(v8::String::New("id"))), + toWebCoreStringWithNullCheck(object->Get(v8::String::New("name"))), + toWebCoreStringWithNullCheck(object->Get(v8::String::New("source"))), + object->Get(v8::String::New("lineOffset"))->ToInteger()->Value()); +} + +void ScriptDebugServer::ensureDebuggerScriptCompiled() +{ + if (m_debuggerScript.get().IsEmpty()) { + v8::HandleScope scope; + v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); + v8::Context::Scope contextScope(debuggerContext); + m_debuggerScript.set(v8::Handle<v8::Object>::Cast(v8::Script::Compile(v8String(m_debuggerScriptSource))->Run())); + } +} + +void ScriptDebugServer::didResume() +{ + m_currentCallFrame.clear(); + m_executionState.clear(); +} + +// Create the utility context for holding JavaScript functions used internally +// which are not visible to JavaScript executing on the page. +void ScriptDebugServer::createUtilityContext() +{ + ASSERT(s_utilityContext.IsEmpty()); + + v8::HandleScope scope; + v8::Handle<v8::ObjectTemplate> globalTemplate = v8::ObjectTemplate::New(); + s_utilityContext = v8::Context::New(0, globalTemplate); + v8::Context::Scope contextScope(s_utilityContext); + + // Compile JavaScript function for retrieving the source line, the source + // name and the symbol name for the top JavaScript stack frame. + DEFINE_STATIC_LOCAL(const char*, topStackFrame, + ("function topStackFrame(exec_state) {" + " if (!exec_state.frameCount())" + " return undefined;" + " var frame = exec_state.frame(0);" + " var func = frame.func();" + " var scriptName;" + " if (func.resolved() && func.script())" + " scriptName = func.script().name();" + " return [scriptName, frame.sourceLine(), (func.name() || func.inferredName())];" + "}")); + v8::Script::Compile(v8::String::New(topStackFrame))->Run(); +} + +bool ScriptDebugServer::topStackFrame(String& sourceName, int& lineNumber, String& functionName) +{ + v8::HandleScope scope; + v8::Handle<v8::Context> v8UtilityContext = utilityContext(); + if (v8UtilityContext.IsEmpty()) + return false; + v8::Context::Scope contextScope(v8UtilityContext); + v8::Handle<v8::Function> topStackFrame; + topStackFrame = v8::Local<v8::Function>::Cast(v8UtilityContext->Global()->Get(v8::String::New("topStackFrame"))); + if (topStackFrame.IsEmpty()) + return false; + v8::Handle<v8::Value> value = v8::Debug::Call(topStackFrame); + if (value.IsEmpty()) + return false; + // If there is no top stack frame, we still return success, but fill the input params with defaults. + if (value->IsUndefined()) { + // Fallback to setting lineNumber to 0, and source and function name to "undefined". + sourceName = toWebCoreString(value); + lineNumber = 0; + functionName = toWebCoreString(value); + return true; + } + if (!value->IsArray()) + return false; + v8::Local<v8::Object> jsArray = value->ToObject(); + v8::Local<v8::Value> sourceNameValue = jsArray->Get(0); + v8::Local<v8::Value> lineNumberValue = jsArray->Get(1); + v8::Local<v8::Value> functionNameValue = jsArray->Get(2); + if (sourceNameValue.IsEmpty() || lineNumberValue.IsEmpty() || functionNameValue.IsEmpty()) + return false; + sourceName = toWebCoreString(sourceNameValue); + lineNumber = lineNumberValue->Int32Value(); + functionName = toWebCoreString(functionNameValue); + return true; } } // namespace WebCore + +#endif // ENABLE(JAVASCRIPT_DEBUGGER) diff --git a/WebCore/bindings/v8/ScriptDebugServer.h b/WebCore/bindings/v8/ScriptDebugServer.h index b37af2f..04857e4 100644 --- a/WebCore/bindings/v8/ScriptDebugServer.h +++ b/WebCore/bindings/v8/ScriptDebugServer.h @@ -31,16 +31,119 @@ #ifndef ScriptDebugServer_h #define ScriptDebugServer_h +#if ENABLE(JAVASCRIPT_DEBUGGER) + +#include "OwnHandle.h" +#include "PlatformString.h" +#include "ScriptBreakpoint.h" +#include "ScriptState.h" +#include "StringHash.h" +#include "Timer.h" +#include <v8-debug.h> +#include <wtf/HashMap.h> #include <wtf/Noncopyable.h> namespace WebCore { +class JavaScriptCallFrame; +class Page; +class ScriptDebugListener; + class ScriptDebugServer : public Noncopyable { public: - static void recompileAllJSFunctions(); - static void recompileAllJSFunctionsSoon(); + static ScriptDebugServer& shared(); + + // Function for retrieving the source name, line number and function name for the top + // JavaScript stack frame. + // + // It will return true if the caller information was successfully retrieved and written + // into the function parameters, otherwise the function will return false. It may + // fail due to a stack overflow in the underlying JavaScript implementation, handling + // of such exception is up to the caller. + static bool topStackFrame(String& sourceName, int& lineNumber, String& functionName); + + 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 pauseOnExceptionsState) { m_pauseOnExceptionsState = pauseOnExceptionsState; } + + void pauseProgram() { } + void continueProgram(); + void stepIntoStatement(); + void stepOverStatement(); + void stepOutOfFunction(); + + void recompileAllJSFunctionsSoon() { } + void recompileAllJSFunctions(Timer<ScriptDebugServer>* = 0) { } + + ScriptState* currentCallFrameState(); + + void pageCreated(Page*) { } + + // v8-specific methods. + void setDebuggerScriptSource(const String& scriptSource); + + typedef void (*MessageLoopDispatchHandler)(const Vector<WebCore::Page*>&); + static void setMessageLoopDispatchHandler(MessageLoopDispatchHandler messageLoopDispatchHandler) { s_messageLoopDispatchHandler = messageLoopDispatchHandler; } + + v8::Handle<v8::Value> currentCallFrameV8(); + PassRefPtr<JavaScriptCallFrame> currentCallFrame(); + +private: + ScriptDebugServer(); + ~ScriptDebugServer() { } + + static void onV8DebugMessage(const v8::Debug::Message& message); + static void onV8DebugHostDispatch(); + + void handleV8DebugMessage(const v8::Debug::Message& message); + void handleV8DebugHostDispatch(); + + void dispatchDidParseSource(ScriptDebugListener* listener, v8::Handle<v8::Object> sourceObject); + + void ensureDebuggerScriptCompiled(); + void didResume(); + + static void createUtilityContext(); + + // Returns a local handle of the utility context. + static v8::Local<v8::Context> utilityContext() + { + if (s_utilityContext.IsEmpty()) + createUtilityContext(); + return v8::Local<v8::Context>::New(s_utilityContext); + } + + // Utility context holding JavaScript functions used internally. + static v8::Persistent<v8::Context> s_utilityContext; + + typedef HashMap<Page*, ScriptDebugListener*> ListenersMap; + ListenersMap m_listenersMap; + typedef HashMap<ScriptDebugListener*, String> ContextDataMap; + ContextDataMap m_contextDataMap; + String m_debuggerScriptSource; + PauseOnExceptionsState m_pauseOnExceptionsState; + OwnHandle<v8::Object> m_debuggerScript; + ScriptState* m_currentCallFrameState; + OwnHandle<v8::Value> m_currentCallFrame; + OwnHandle<v8::Object> m_executionState; + + static MessageLoopDispatchHandler s_messageLoopDispatchHandler; }; } // namespace WebCore +#endif // ENABLE(JAVASCRIPT_DEBUGGER) + #endif // ScriptDebugServer_h diff --git a/WebCore/bindings/v8/ScriptEventListener.cpp b/WebCore/bindings/v8/ScriptEventListener.cpp index b318d2e..fdb6076 100644 --- a/WebCore/bindings/v8/ScriptEventListener.cpp +++ b/WebCore/bindings/v8/ScriptEventListener.cpp @@ -56,7 +56,7 @@ PassRefPtr<V8LazyEventListener> createAttributeEventListener(Node* node, Attribu 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())) { @@ -89,7 +89,7 @@ PassRefPtr<V8LazyEventListener> 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())) { diff --git a/WebCore/bindings/v8/ScriptGCEvent.cpp b/WebCore/bindings/v8/ScriptGCEvent.cpp new file mode 100644 index 0000000..a58a0cd --- /dev/null +++ b/WebCore/bindings/v8/ScriptGCEvent.cpp @@ -0,0 +1,101 @@ +/* +* 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(INSPECTOR) + +#include "ScriptGCEvent.h" +#include "ScriptGCEventListener.h" + +#include <wtf/CurrentTime.h> + +namespace WebCore { + +ScriptGCEvent::GCEventListeners ScriptGCEvent::s_eventListeners; +double ScriptGCEvent::s_startTime = 0.0; +size_t ScriptGCEvent::s_usedHeapSize = 0; + +void ScriptGCEvent::addEventListener(ScriptGCEventListener* eventListener) +{ + ASSERT(eventListener); + if (s_eventListeners.isEmpty()) { + v8::V8::AddGCPrologueCallback(ScriptGCEvent::gcPrologueCallback); + v8::V8::AddGCEpilogueCallback(ScriptGCEvent::gcEpilogueCallback); + } + s_eventListeners.append(eventListener); +} + +void ScriptGCEvent::removeEventListener(ScriptGCEventListener* eventListener) +{ + ASSERT(eventListener); + ASSERT(!s_eventListeners.isEmpty()); + size_t i = s_eventListeners.find(eventListener); + ASSERT(i != notFound); + s_eventListeners.remove(i); + if (s_eventListeners.isEmpty()) { + v8::V8::RemoveGCPrologueCallback(ScriptGCEvent::gcPrologueCallback); + v8::V8::RemoveGCEpilogueCallback(ScriptGCEvent::gcEpilogueCallback); + } +} + +void ScriptGCEvent::getHeapSize(size_t& usedHeapSize, size_t& totalHeapSize) +{ + v8::HeapStatistics heapStatistics; + v8::V8::GetHeapStatistics(&heapStatistics); + usedHeapSize = heapStatistics.used_heap_size(); + totalHeapSize = heapStatistics.total_heap_size(); +} + +size_t ScriptGCEvent::getUsedHeapSize() +{ + v8::HeapStatistics heapStatistics; + v8::V8::GetHeapStatistics(&heapStatistics); + return heapStatistics.used_heap_size(); +} + +void ScriptGCEvent::gcPrologueCallback(v8::GCType type, v8::GCCallbackFlags flags) +{ + s_startTime = WTF::currentTimeMS(); + s_usedHeapSize = getUsedHeapSize(); +} + +void ScriptGCEvent::gcEpilogueCallback(v8::GCType type, v8::GCCallbackFlags flags) +{ + double endTime = WTF::currentTimeMS(); + size_t collectedBytes = s_usedHeapSize - getUsedHeapSize(); + GCEventListeners listeners(s_eventListeners); + for (GCEventListeners::iterator i = listeners.begin(); i != listeners.end(); ++i) + (*i)->didGC(s_startTime, endTime, collectedBytes); +} + +} // namespace WebCore + +#endif // ENABLE(INSPECTOR) diff --git a/WebCore/bindings/v8/ScriptGCEvent.h b/WebCore/bindings/v8/ScriptGCEvent.h new file mode 100644 index 0000000..80a5a38 --- /dev/null +++ b/WebCore/bindings/v8/ScriptGCEvent.h @@ -0,0 +1,63 @@ +/* +* 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) + +#include "v8.h" +#include <wtf/Vector.h> + +namespace WebCore { + +class ScriptGCEventListener; + +class ScriptGCEvent +{ +public: + static void addEventListener(ScriptGCEventListener*); + static void removeEventListener(ScriptGCEventListener*); + static void getHeapSize(size_t&, size_t&); +private: + typedef Vector<ScriptGCEventListener*> GCEventListeners; + static GCEventListeners s_eventListeners; + static double s_startTime; + static size_t s_usedHeapSize; + + static void gcEpilogueCallback(v8::GCType type, v8::GCCallbackFlags flags); + static void gcPrologueCallback(v8::GCType type, v8::GCCallbackFlags flags); + static size_t getUsedHeapSize(); +}; + +} // namespace WebCore + +#endif // !ENABLE(INSPECTOR) +#endif // !defined(ScriptGCEvent_h) diff --git a/WebCore/bindings/v8/custom/V8DOMSelectionCustom.cpp b/WebCore/bindings/v8/ScriptProfile.cpp index 0c9e745..beafea1 100644 --- a/WebCore/bindings/v8/custom/V8DOMSelectionCustom.cpp +++ b/WebCore/bindings/v8/ScriptProfile.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 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 @@ -29,23 +29,28 @@ */ #include "config.h" -#include "V8DOMSelection.h" -#include "V8DOMWindow.h" -#include "V8DOMWrapper.h" +#include "ScriptProfile.h" + +#include "V8Binding.h" + +#include <v8-profiler.h> namespace WebCore { -v8::Handle<v8::Value> toV8(DOMSelection* impl) +String ScriptProfile::title() const +{ + return toWebCoreString(m_profile->GetTitle()); +} + +unsigned int ScriptProfile::uid() const +{ + return m_profile->GetUid(); +} + +PassRefPtr<ScriptProfileNode> ScriptProfile::head() const { - if (!impl) - return v8::Null(); - v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(impl); - if (wrapper.IsEmpty()) { - wrapper = V8DOMSelection::wrap(impl); - V8DOMWrapper::setHiddenWindowReference(impl->frame(), V8DOMWindow::domSelectionIndex, wrapper); - } - return wrapper; + return ScriptProfileNode::create(m_profile->GetTopDownRoot()); } } // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptProfile.h b/WebCore/bindings/v8/ScriptProfile.h index 1a4d677..2f42ad2 100644 --- a/WebCore/bindings/v8/ScriptProfile.h +++ b/WebCore/bindings/v8/ScriptProfile.h @@ -32,29 +32,33 @@ #define ScriptProfile_h #include "PlatformString.h" +#include "ScriptProfileNode.h" + +namespace v8 { +class CpuProfile; +} namespace WebCore { class ScriptProfile : public RefCounted<ScriptProfile> { public: - static PassRefPtr<ScriptProfile> create(const String& title, unsigned uid) + static PassRefPtr<ScriptProfile> create(const v8::CpuProfile* profile) { - return adoptRef(new ScriptProfile(title, uid)); + return adoptRef(new ScriptProfile(profile)); } virtual ~ScriptProfile() {} - String title() const { return m_title; } - unsigned int uid() const { return m_uid; } + String title() const; + unsigned int uid() const; + PassRefPtr<ScriptProfileNode> head() const; protected: - ScriptProfile(const String& title, unsigned uid) - : m_title(title) - , m_uid(uid) + ScriptProfile(const v8::CpuProfile* profile) + : m_profile(profile) {} private: - String m_title; - unsigned int m_uid; + const v8::CpuProfile* m_profile; }; } // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptProfileNode.cpp b/WebCore/bindings/v8/ScriptProfileNode.cpp new file mode 100644 index 0000000..3121128 --- /dev/null +++ b/WebCore/bindings/v8/ScriptProfileNode.cpp @@ -0,0 +1,92 @@ +/* + * 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 "ScriptProfile.h" + +#include "V8Binding.h" + +#include <v8-profiler.h> + +namespace WebCore { + +String ScriptProfileNode::functionName() const +{ + return toWebCoreString(m_profileNode->GetFunctionName()); +} + +String ScriptProfileNode::url() const +{ + return toWebCoreString(m_profileNode->GetScriptResourceName()); +} + +unsigned long ScriptProfileNode::lineNumber() const +{ + return m_profileNode->GetLineNumber(); +} + +double ScriptProfileNode::totalTime() const +{ + // FIXME: use GetTotalMilliseconds once it is implemented in V8. + return m_profileNode->GetTotalSamplesCount(); +} + +double ScriptProfileNode::selfTime() const +{ + // FIXME: use GetSelfMilliseconds once it is implemented in V8. + return m_profileNode->GetSelfSamplesCount(); +} + +unsigned long ScriptProfileNode::numberOfCalls() const +{ + return 0; +} + +ProfileNodesList ScriptProfileNode::children() const +{ + const int childrenCount = m_profileNode->GetChildrenCount(); + ProfileNodesList result(childrenCount); + for (int i = 0; i < childrenCount; ++i) + result[i] = ScriptProfileNode::create(m_profileNode->GetChild(i)); + return result; +} + +bool ScriptProfileNode::visible() const +{ + return true; +} + +unsigned long ScriptProfileNode::callUID() const +{ + return m_profileNode->GetCallUid(); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptProfileNode.h b/WebCore/bindings/v8/ScriptProfileNode.h new file mode 100644 index 0000000..5acf319 --- /dev/null +++ b/WebCore/bindings/v8/ScriptProfileNode.h @@ -0,0 +1,75 @@ +/* + * 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 ScriptProfileNode_h +#define ScriptProfileNode_h + +#include "PlatformString.h" + +namespace v8 { +class CpuProfileNode; +} + +namespace WebCore { + +class ScriptProfileNode; + +typedef Vector<RefPtr<ScriptProfileNode> > ProfileNodesList; + +class ScriptProfileNode : public RefCounted<ScriptProfileNode> { +public: + static PassRefPtr<ScriptProfileNode> create(const v8::CpuProfileNode* profileNode) + { + return adoptRef(new ScriptProfileNode(profileNode)); + } + virtual ~ScriptProfileNode() {} + + String functionName() const; + String url() const; + unsigned long lineNumber() const; + double totalTime() const; + double selfTime() const; + unsigned long numberOfCalls() const; + ProfileNodesList children() const; + bool visible() const; + unsigned long callUID() const; + +protected: + ScriptProfileNode(const v8::CpuProfileNode* profileNode) + : m_profileNode(profileNode) + {} + +private: + const v8::CpuProfileNode* m_profileNode; +}; + +} // namespace WebCore + +#endif // ScriptProfileNode_h diff --git a/WebCore/bindings/v8/ScriptProfiler.cpp b/WebCore/bindings/v8/ScriptProfiler.cpp index f238f6f..1f09420 100644 --- a/WebCore/bindings/v8/ScriptProfiler.cpp +++ b/WebCore/bindings/v8/ScriptProfiler.cpp @@ -31,20 +31,23 @@ #include "config.h" #include "ScriptProfiler.h" +#include "ScriptString.h" + +#include <v8-profiler.h> namespace WebCore { void ScriptProfiler::start(ScriptState* state, const String& title) { - v8::HandleScope scope; - v8::Context::Scope contextScope(v8::Context::GetCurrent()); - v8::V8::ResumeProfiler(); + v8::HandleScope hs; + v8::CpuProfiler::StartProfiling(v8String(title)); } PassRefPtr<ScriptProfile> ScriptProfiler::stop(ScriptState* state, const String& title) { - v8::V8::PauseProfiler(); - return 0; + v8::HandleScope hs; + const v8::CpuProfile* profile = v8::CpuProfiler::StopProfiling(v8String(title)); + return profile ? ScriptProfile::create(profile) : 0; } } // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptState.h b/WebCore/bindings/v8/ScriptState.h index 5c5ce6c..ce350da 100644 --- a/WebCore/bindings/v8/ScriptState.h +++ b/WebCore/bindings/v8/ScriptState.h @@ -37,55 +37,77 @@ #include <wtf/RefCounted.h> namespace WebCore { - class DOMWrapperWorld; - class Frame; - class Node; - class Page; - - class ScriptState : public Noncopyable { - public: - bool hadException() { return !m_exception.IsEmpty(); } - void setException(v8::Local<v8::Value> exception) - { - m_exception = exception; +class DOMWrapperWorld; +class Frame; +class Node; +class Page; + +class ScriptState : public Noncopyable { +public: + bool hadException() { return !m_exception.IsEmpty(); } + void setException(v8::Local<v8::Value> exception) + { + m_exception = exception; + } + v8::Local<v8::Value> exception() { return m_exception; } + + v8::Local<v8::Context> context() const + { + return v8::Local<v8::Context>::New(m_context); + } + + static ScriptState* forContext(v8::Local<v8::Context>); + static ScriptState* current(); + +protected: + ScriptState() { } + ~ScriptState(); + +private: + friend ScriptState* mainWorldScriptState(Frame*); + explicit ScriptState(v8::Handle<v8::Context>); + + static void weakReferenceCallback(v8::Persistent<v8::Value> object, void* parameter); + + v8::Local<v8::Value> m_exception; + v8::Persistent<v8::Context> m_context; +}; + +class EmptyScriptState : public ScriptState { +public: + EmptyScriptState() : ScriptState() { } + ~EmptyScriptState() { } +}; + +class ScriptStateProtectedPtr : public Noncopyable { +public: + ScriptStateProtectedPtr() : m_scriptState(0) { } + ScriptStateProtectedPtr(ScriptState* scriptState) : m_scriptState(scriptState) + { + v8::HandleScope handleScope; + // Keep the context from being GC'ed. ScriptState is guaranteed to be live while the context is live. + m_context = v8::Persistent<v8::Context>::New(scriptState->context()); + } + ~ScriptStateProtectedPtr() + { + if (!m_context.IsEmpty()) { + m_context.Dispose(); + m_context.Clear(); } - v8::Local<v8::Value> exception() { return m_exception; } + } + ScriptState* get() { return m_scriptState; } +private: + ScriptState* m_scriptState; + v8::Persistent<v8::Context> m_context; +}; - v8::Local<v8::Context> context() const - { - return v8::Local<v8::Context>::New(m_context); - } - - static ScriptState* forContext(v8::Local<v8::Context>); - static ScriptState* current(); - - protected: - ScriptState() { } - ~ScriptState(); - - private: - friend ScriptState* mainWorldScriptState(Frame*); - explicit ScriptState(v8::Handle<v8::Context>); - - static void weakReferenceCallback(v8::Persistent<v8::Value> object, void* parameter); - - v8::Local<v8::Value> m_exception; - v8::Persistent<v8::Context> m_context; - }; - - class EmptyScriptState : public ScriptState { - public: - EmptyScriptState() : ScriptState() { } - ~EmptyScriptState() { } - }; - - ScriptState* mainWorldScriptState(Frame*); +ScriptState* mainWorldScriptState(Frame*); - ScriptState* scriptStateFromNode(DOMWrapperWorld*, Node*); - ScriptState* scriptStateFromPage(DOMWrapperWorld*, Page*); +ScriptState* scriptStateFromNode(DOMWrapperWorld*, Node*); +ScriptState* scriptStateFromPage(DOMWrapperWorld*, Page*); - inline DOMWrapperWorld* debuggerWorld() { return mainThreadNormalWorld(); } - inline DOMWrapperWorld* pluginWorld() { return mainThreadNormalWorld(); } +inline DOMWrapperWorld* debuggerWorld() { return mainThreadNormalWorld(); } +inline DOMWrapperWorld* pluginWorld() { return mainThreadNormalWorld(); } } diff --git a/WebCore/bindings/v8/ScriptValue.h b/WebCore/bindings/v8/ScriptValue.h index 1713f80..8241205 100644 --- a/WebCore/bindings/v8/ScriptValue.h +++ b/WebCore/bindings/v8/ScriptValue.h @@ -127,6 +127,8 @@ public: PassRefPtr<SerializedScriptValue> serialize(ScriptState*); static ScriptValue deserialize(ScriptState*, SerializedScriptValue*); + static ScriptValue undefined() { return ScriptValue(v8::Undefined()); } + void clear() { if (m_value.IsEmpty()) diff --git a/WebCore/bindings/v8/SerializedScriptValue.cpp b/WebCore/bindings/v8/SerializedScriptValue.cpp index bac7f20..50ac86b 100644 --- a/WebCore/bindings/v8/SerializedScriptValue.cpp +++ b/WebCore/bindings/v8/SerializedScriptValue.cpp @@ -31,7 +31,18 @@ #include "config.h" #include "SerializedScriptValue.h" +#include "Blob.h" +#include "ByteArray.h" +#include "CanvasPixelArray.h" +#include "File.h" +#include "FileList.h" +#include "ImageData.h" #include "SharedBuffer.h" +#include "V8Blob.h" +#include "V8File.h" +#include "V8FileList.h" +#include "V8ImageData.h" +#include "V8Proxy.h" #include <v8.h> #include <wtf/Assertions.h> @@ -40,7 +51,6 @@ // FIXME: // - catch V8 exceptions -// - be ready to get empty handles // - consider crashing in debug mode on deserialization errors namespace WebCore { @@ -60,19 +70,18 @@ enum SerializationTag { FalseTag = 'F', StringTag = 'S', Int32Tag = 'I', + Uint32Tag = 'U', + DateTag = 'D', NumberTag = 'N', - ObjectTag = '{', + BlobTag = 'b', + FileTag = 'f', + FileListTag = 'l', + ImageDataTag = '#', ArrayTag = '[', + ObjectTag = '{', + SparseArrayTag = '@', }; -// Helpers to do verbose handle casts. - -template <typename T, typename U> -static v8::Handle<T> handleCast(v8::Handle<U> handle) { return v8::Handle<T>::Cast(handle); } - -template <typename T, typename U> -static v8::Local<T> handleCast(v8::Local<U> handle) { return v8::Local<T>::Cast(handle); } - static bool shouldCheckForCycles(int depth) { ASSERT(depth >= 0); @@ -118,7 +127,8 @@ private: // information used to reconstruct composite types. class Writer : Noncopyable { public: - Writer() : m_position(0) + Writer() + : m_position(0) { } @@ -134,9 +144,17 @@ public: void writeString(const char* data, int length) { + ASSERT(length >= 0); append(StringTag); - doWriteUint32(static_cast<uint32_t>(length)); - append(data, length); + doWriteString(data, length); + } + + void writeWebCoreString(const String& string) + { + // Uses UTF8 encoding so we can read it back as either V8 or + // WebCore string. + append(StringTag); + doWriteWebCoreString(string); } void writeInt32(int32_t value) @@ -145,19 +163,71 @@ public: doWriteUint32(ZigZag::encode(static_cast<uint32_t>(value))); } + void writeUint32(uint32_t value) + { + append(Uint32Tag); + doWriteUint32(value); + } + + void writeDate(double numberValue) + { + append(DateTag); + doWriteNumber(numberValue); + } + void writeNumber(double number) { append(NumberTag); - append(reinterpret_cast<char*>(&number), sizeof(number)); + doWriteNumber(number); } - // Records that a composite object can be constructed by using - // |length| previously stored values. - void endComposite(SerializationTag tag, int32_t length) + void writeBlob(const String& path) { - ASSERT(tag == ObjectTag || tag == ArrayTag); - append(tag); - doWriteUint32(static_cast<uint32_t>(length)); + append(BlobTag); + doWriteWebCoreString(path); + } + + void writeFile(const String& path) + { + append(FileTag); + doWriteWebCoreString(path); + } + + void writeFileList(const FileList& fileList) + { + append(FileListTag); + uint32_t length = fileList.length(); + doWriteUint32(length); + for (unsigned i = 0; i < length; ++i) + doWriteWebCoreString(fileList.item(i)->path()); + } + + void writeImageData(uint32_t width, uint32_t height, const uint8_t* pixelData, uint32_t pixelDataLength) + { + append(ImageDataTag); + doWriteUint32(width); + doWriteUint32(height); + doWriteUint32(pixelDataLength); + append(pixelData, pixelDataLength); + } + + void writeArray(uint32_t length) + { + append(ArrayTag); + doWriteUint32(length); + } + + void writeObject(uint32_t numProperties) + { + append(ObjectTag); + doWriteUint32(numProperties); + } + + void writeSparseArray(uint32_t numProperties, uint32_t length) + { + append(SparseArrayTag); + doWriteUint32(numProperties); + doWriteUint32(length); } Vector<BufferValueType>& data() @@ -167,10 +237,22 @@ public: } private: + void doWriteString(const char* data, int length) + { + doWriteUint32(static_cast<uint32_t>(length)); + append(reinterpret_cast<const uint8_t*>(data), length); + } + + void doWriteWebCoreString(const String& string) + { + RefPtr<SharedBuffer> buffer = utf8Buffer(string); + doWriteString(buffer->data(), buffer->size()); + } + void doWriteUint32(uint32_t value) { while (true) { - char b = (value & varIntMask); + uint8_t b = (value & varIntMask); value >>= varIntShift; if (!value) { append(b); @@ -180,21 +262,26 @@ private: } } + void doWriteNumber(double number) + { + append(reinterpret_cast<uint8_t*>(&number), sizeof(number)); + } + void append(SerializationTag tag) { - append(static_cast<char>(tag)); + append(static_cast<uint8_t>(tag)); } - void append(char b) + void append(uint8_t b) { ensureSpace(1); - *charAt(m_position++) = b; + *byteAt(m_position++) = b; } - void append(const char* data, int length) + void append(const uint8_t* data, int length) { ensureSpace(length); - memcpy(charAt(m_position), data, length); + memcpy(byteAt(m_position), data, length); m_position += length; } @@ -210,41 +297,54 @@ private: // If the writer is at odd position in the buffer, then one of // the bytes in the last UChar is not initialized. if (m_position % 2) - *charAt(m_position) = static_cast<char>(PaddingTag); + *byteAt(m_position) = static_cast<uint8_t>(PaddingTag); } - char* charAt(int position) { return reinterpret_cast<char*>(m_buffer.data()) + position; } + uint8_t* byteAt(int position) { return reinterpret_cast<uint8_t*>(m_buffer.data()) + position; } Vector<BufferValueType> m_buffer; unsigned m_position; }; class Serializer { + class StateBase; public: explicit Serializer(Writer& writer) : m_writer(writer) - , m_state(0) , m_depth(0) + , m_hasError(false) { } bool serialize(v8::Handle<v8::Value> value) { v8::HandleScope scope; - StackCleaner cleaner(&m_state); - if (!doSerialize(value)) - return false; - while (top()) { - int length; - while (!top()->isDone(&length)) { - // Note that doSerialize() can change current top(). - if (!doSerialize(top()->advance())) - return false; - } - m_writer.endComposite(top()->tag(), length); - pop(); - } - return true; + StateBase* state = doSerialize(value, 0); + while (state) + state = state->advance(*this); + return !m_hasError; + } + + // Functions used by serialization states. + + StateBase* doSerialize(v8::Handle<v8::Value> value, StateBase* next); + + StateBase* writeArray(uint32_t length, StateBase* state) + { + m_writer.writeArray(length); + return pop(state); + } + + StateBase* writeObject(uint32_t numProperties, StateBase* state) + { + m_writer.writeObject(numProperties); + return pop(state); + } + + StateBase* writeSparseArray(uint32_t numProperties, uint32_t length, StateBase* state) + { + m_writer.writeSparseArray(numProperties, length); + return pop(state); } private: @@ -254,221 +354,308 @@ private: // Link to the next state to form a stack. StateBase* nextState() { return m_next; } - void setNextState(StateBase* next) { m_next = next; } // Composite object we're processing in this state. v8::Handle<v8::Value> composite() { return m_composite; } - // Serialization tag for the current composite. - virtual SerializationTag tag() const = 0; - - // Returns whether iteration over subobjects of the current - // composite object is done. If yes, |*length| is set to the - // number of subobjects. - virtual bool isDone(int* length) = 0; - - // Advances to the next subobject. - // Requires: !this->isDone(). - virtual v8::Local<v8::Value> advance() = 0; + // Serializes (a part of) the current composite and returns + // the next state to process or null when this is the final + // state. + virtual StateBase* advance(Serializer&) = 0; protected: - StateBase(v8::Handle<v8::Value> composite) - : m_next(0) - , m_composite(composite) + StateBase(v8::Handle<v8::Value> composite, StateBase* next) + : m_composite(composite) + , m_next(next) { } private: - StateBase* m_next; v8::Handle<v8::Value> m_composite; + StateBase* m_next; }; - template <typename T, SerializationTag compositeTag> - class State : public StateBase { + // Dummy state that is used to signal serialization errors. + class ErrorState : public StateBase { public: - v8::Handle<T> composite() { return handleCast<T>(StateBase::composite()); } + ErrorState() + : StateBase(v8::Handle<v8::Value>(), 0) + { + } - virtual SerializationTag tag() const { return compositeTag; } + virtual StateBase* advance(Serializer&) + { + delete this; + return 0; + } + }; + + template <typename T> + class State : public StateBase { + public: + v8::Handle<T> composite() { return v8::Handle<T>::Cast(StateBase::composite()); } protected: - explicit State(v8::Handle<T> composite) : StateBase(composite) + State(v8::Handle<T> composite, StateBase* next) + : StateBase(composite, next) { } }; - // Helper to clean up the state stack in case of errors. - class StackCleaner : Noncopyable { +#if 0 + // Currently unused, see comment in newArrayState. + class ArrayState : public State<v8::Array> { public: - explicit StackCleaner(StateBase** stack) : m_stack(stack) + ArrayState(v8::Handle<v8::Array> array, StateBase* next) + : State<v8::Array>(array, next) + , m_index(-1) { } - ~StackCleaner() + virtual StateBase* advance(Serializer& serializer) { - StateBase* state = *m_stack; - while (state) { - StateBase* tmp = state->nextState(); - delete state; - state = tmp; + ++m_index; + for (; m_index < composite()->Length(); ++m_index) { + if (StateBase* newState = serializer.doSerialize(composite()->Get(m_index), this)) + return newState; } - *m_stack = 0; + return serializer.writeArray(composite()->Length(), this); } private: - StateBase** m_stack; + unsigned m_index; }; +#endif - class ArrayState : public State<v8::Array, ArrayTag> { + class AbstractObjectState : public State<v8::Object> { public: - ArrayState(v8::Handle<v8::Array> array) - : State<v8::Array, ArrayTag>(array) - , m_index(0) + AbstractObjectState(v8::Handle<v8::Object> object, StateBase* next) + : State<v8::Object>(object, next) + , m_propertyNames(object->GetPropertyNames()) + , m_index(-1) + , m_numSerializedProperties(0) + , m_nameDone(false) { } - virtual bool isDone(int* length) + virtual StateBase* advance(Serializer& serializer) { - *length = composite()->Length(); - return static_cast<int>(m_index) >= *length; + ++m_index; + for (; m_index < m_propertyNames->Length(); ++m_index) { + if (m_propertyName.IsEmpty()) { + v8::Local<v8::Value> propertyName = m_propertyNames->Get(m_index); + if ((propertyName->IsString() && composite()->HasRealNamedProperty(propertyName.As<v8::String>())) + || (propertyName->IsUint32() && composite()->HasRealIndexedProperty(propertyName->Uint32Value()))) { + m_propertyName = propertyName; + } else + continue; + } + ASSERT(!m_propertyName.IsEmpty()); + if (!m_nameDone) { + m_nameDone = true; + if (StateBase* newState = serializer.doSerialize(m_propertyName, this)) + return newState; + } + v8::Local<v8::Value> value = composite()->Get(m_propertyName); + m_nameDone = false; + m_propertyName.Clear(); + ++m_numSerializedProperties; + if (StateBase* newState = serializer.doSerialize(value, this)) + return newState; + } + return objectDone(m_numSerializedProperties, serializer); } - virtual v8::Local<v8::Value> advance() - { - ASSERT(m_index < composite()->Length()); - v8::HandleScope scope; - return scope.Close(composite()->Get(v8::Integer::New(m_index++))); - } + protected: + virtual StateBase* objectDone(unsigned numProperties, Serializer&) = 0; private: + v8::Local<v8::Array> m_propertyNames; + v8::Local<v8::Value> m_propertyName; unsigned m_index; + unsigned m_numSerializedProperties; + bool m_nameDone; }; - class ObjectState : public State<v8::Object, ObjectTag> { + class ObjectState : public AbstractObjectState { public: - ObjectState(v8::Handle<v8::Object> object) - : State<v8::Object, ObjectTag>(object) - , m_propertyNames(object->GetPropertyNames()) - , m_index(-1) - , m_length(0) + ObjectState(v8::Handle<v8::Object> object, StateBase* next) + : AbstractObjectState(object, next) { - nextProperty(); } - virtual bool isDone(int* length) + protected: + virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) { - *length = m_length; - return m_index >= 2 * m_propertyNames->Length(); + return serializer.writeObject(numProperties, this); } + }; - virtual v8::Local<v8::Value> advance() + class SparseArrayState : public AbstractObjectState { + public: + SparseArrayState(v8::Handle<v8::Array> array, StateBase* next) + : AbstractObjectState(array, next) { - ASSERT(m_index < 2 * m_propertyNames->Length()); - if (!(m_index % 2)) { - ++m_index; - return m_propertyName; - } - v8::Local<v8::Value> result = composite()->Get(m_propertyName); - nextProperty(); - return result; } - private: - void nextProperty() + protected: + virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) { - v8::HandleScope scope; - ++m_index; - ASSERT(!(m_index % 2)); - for (; m_index < 2 * m_propertyNames->Length(); m_index += 2) { - v8::Local<v8::Value> propertyName = m_propertyNames->Get(v8::Integer::New(m_index / 2)); - if ((propertyName->IsString() && composite()->HasRealNamedProperty(handleCast<v8::String>(propertyName))) - || (propertyName->IsInt32() && composite()->HasRealIndexedProperty(propertyName->Uint32Value()))) { - m_propertyName = scope.Close(propertyName); - m_length += 2; - return; - } - } + return serializer.writeSparseArray(numProperties, composite().As<v8::Array>()->Length(), this); } - - v8::Local<v8::Array> m_propertyNames; - v8::Local<v8::Value> m_propertyName; - unsigned m_index; - unsigned m_length; }; - bool doSerialize(v8::Handle<v8::Value> value) - { - if (value->IsUndefined()) - m_writer.writeUndefined(); - else if (value->IsNull()) - m_writer.writeNull(); - else if (value->IsTrue()) - m_writer.writeTrue(); - else if (value->IsFalse()) - m_writer.writeFalse(); - else if (value->IsInt32()) - m_writer.writeInt32(value->Int32Value()); - else if (value->IsNumber()) - m_writer.writeNumber(handleCast<v8::Number>(value)->Value()); - else if (value->IsString()) { - v8::String::Utf8Value stringValue(value); - m_writer.writeString(*stringValue, stringValue.length()); - } else if (value->IsArray()) { - if (!checkComposite(value)) - return false; - push(new ArrayState(handleCast<v8::Array>(value))); - } else if (value->IsObject()) { - if (!checkComposite(value)) - return false; - push(new ObjectState(handleCast<v8::Object>(value))); - // FIXME: - // - check not a wrapper - // - support File, ImageData, etc. - } - return true; - } - - void push(StateBase* state) + StateBase* push(StateBase* state) { - state->setNextState(m_state); - m_state = state; + ASSERT(state); ++m_depth; + return checkComposite(state) ? state : handleError(state); } - StateBase* top() { return m_state; } - - void pop() + StateBase* pop(StateBase* state) { - if (!m_state) - return; - StateBase* top = m_state; - m_state = top->nextState(); - delete top; + ASSERT(state); --m_depth; + StateBase* next = state->nextState(); + delete state; + return next; + } + + StateBase* handleError(StateBase* state) + { + m_hasError = true; + while (state) { + StateBase* tmp = state->nextState(); + delete state; + state = tmp; + } + return new ErrorState; } - bool checkComposite(v8::Handle<v8::Value> composite) + bool checkComposite(StateBase* top) { + ASSERT(top); if (m_depth > maxDepth) return false; if (!shouldCheckForCycles(m_depth)) return true; - for (StateBase* state = top(); state; state = state->nextState()) { + v8::Handle<v8::Value> composite = top->composite(); + for (StateBase* state = top->nextState(); state; state = state->nextState()) { if (state->composite() == composite) return false; } return true; } + void writeString(v8::Handle<v8::Value> value) + { + v8::String::Utf8Value stringValue(value); + m_writer.writeString(*stringValue, stringValue.length()); + } + + void writeBlob(v8::Handle<v8::Value> value) + { + Blob* blob = V8Blob::toNative(value.As<v8::Object>()); + if (!blob) + return; + m_writer.writeBlob(blob->path()); + } + + void writeFile(v8::Handle<v8::Value> value) + { + File* file = V8File::toNative(value.As<v8::Object>()); + if (!file) + return; + m_writer.writeFile(file->path()); + } + + void writeFileList(v8::Handle<v8::Value> value) + { + FileList* fileList = V8FileList::toNative(value.As<v8::Object>()); + if (!fileList) + return; + m_writer.writeFileList(*fileList); + } + + void writeImageData(v8::Handle<v8::Value> value) + { + ImageData* imageData = V8ImageData::toNative(value.As<v8::Object>()); + if (!imageData) + return; + WTF::ByteArray* pixelArray = imageData->data()->data(); + m_writer.writeImageData(imageData->width(), imageData->height(), pixelArray->data(), pixelArray->length()); + } + + static StateBase* newArrayState(v8::Handle<v8::Array> array, StateBase* next) + { + // FIXME: use plain Array state when we can quickly check that + // an array is not sparse and has only indexed properties. + return new SparseArrayState(array, next); + } + + static StateBase* newObjectState(v8::Handle<v8::Object> object, StateBase* next) + { + // FIXME: + // - check not a wrapper + // - support File, etc. + return new ObjectState(object, next); + } + Writer& m_writer; - StateBase* m_state; int m_depth; + bool m_hasError; +}; + +Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, StateBase* next) +{ + if (value->IsUndefined()) + m_writer.writeUndefined(); + else if (value->IsNull()) + m_writer.writeNull(); + else if (value->IsTrue()) + m_writer.writeTrue(); + else if (value->IsFalse()) + m_writer.writeFalse(); + else if (value->IsInt32()) + m_writer.writeInt32(value->Int32Value()); + else if (value->IsUint32()) + m_writer.writeUint32(value->Uint32Value()); + else if (value->IsDate()) + m_writer.writeDate(value->NumberValue()); + else if (value->IsNumber()) + m_writer.writeNumber(value.As<v8::Number>()->Value()); + else if (value->IsString()) + writeString(value); + else if (value->IsArray()) + return push(newArrayState(value.As<v8::Array>(), next)); + else if (V8File::HasInstance(value)) + writeFile(value); + else if (V8Blob::HasInstance(value)) + writeBlob(value); + else if (V8FileList::HasInstance(value)) + writeFileList(value); + else if (V8ImageData::HasInstance(value)) + writeImageData(value); + else if (value->IsObject()) + return push(newObjectState(value.As<v8::Object>(), next)); + return 0; +} + +// Interface used by Reader to create objects of composite types. +class CompositeCreator { +public: + virtual ~CompositeCreator() { } + + virtual bool createArray(uint32_t length, v8::Handle<v8::Value>* value) = 0; + virtual bool createObject(uint32_t numProperties, v8::Handle<v8::Value>* value) = 0; + virtual bool createSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value) = 0; }; // Reader is responsible for deserializing primitive types and // restoring information about saved objects of composite types. class Reader { public: - Reader(const char* buffer, int length) + Reader(const uint8_t* buffer, int length) : m_buffer(buffer) , m_length(length) , m_position(0) @@ -478,16 +665,16 @@ public: bool isEof() const { return m_position >= m_length; } - bool read(SerializationTag* tag, v8::Handle<v8::Value>* value, int* length) + bool read(v8::Handle<v8::Value>* value, CompositeCreator& creator) { - uint32_t rawLength; - if (!readTag(tag)) + SerializationTag tag; + if (!readTag(&tag)) return false; - switch (*tag) { + switch (tag) { case InvalidTag: return false; case PaddingTag: - break; + return true; case UndefinedTag: *value = v8::Undefined(); break; @@ -508,18 +695,65 @@ public: if (!readInt32(value)) return false; break; + case Uint32Tag: + if (!readUint32(value)) + return false; + break; + case DateTag: + if (!readDate(value)) + return false; + break; case NumberTag: if (!readNumber(value)) return false; break; - case ObjectTag: - case ArrayTag: - if (!doReadUint32(&rawLength)) + case BlobTag: + if (!readBlob(value)) + return false; + break; + case FileTag: + if (!readFile(value)) + return false; + break; + case FileListTag: + if (!readFileList(value)) + return false; + break; + case ImageDataTag: + if (!readImageData(value)) + return false; + break; + case ArrayTag: { + uint32_t length; + if (!doReadUint32(&length)) + return false; + if (!creator.createArray(length, value)) return false; - *length = rawLength; break; } - return true; + case ObjectTag: { + uint32_t numProperties; + if (!doReadUint32(&numProperties)) + return false; + if (!creator.createObject(numProperties, value)) + return false; + break; + } + case SparseArrayTag: { + uint32_t numProperties; + uint32_t length; + if (!doReadUint32(&numProperties)) + return false; + if (!doReadUint32(&length)) + return false; + if (!creator.createSparseArray(numProperties, length, value)) + return false; + break; + } + default: + return false; + } + return !value->IsEmpty(); } private: @@ -538,7 +772,19 @@ private: return false; if (m_position + length > m_length) return false; - *value = v8::String::New(m_buffer + m_position, length); + *value = v8::String::New(reinterpret_cast<const char*>(m_buffer + m_position), length); + m_position += length; + return true; + } + + bool readWebCoreString(String* string) + { + uint32_t length; + if (!doReadUint32(&length)) + return false; + if (m_position + length > m_length) + return false; + *string = String::fromUTF8(reinterpret_cast<const char*>(m_buffer + m_position), length); m_position += length; return true; } @@ -552,22 +798,96 @@ private: return true; } - bool readNumber(v8::Handle<v8::Value>* value) + bool readUint32(v8::Handle<v8::Value>* value) { - if (m_position + sizeof(double) > m_length) + uint32_t rawValue; + if (!doReadUint32(&rawValue)) + return false; + *value = v8::Integer::New(rawValue); + return true; + } + + bool readDate(v8::Handle<v8::Value>* value) + { + double numberValue; + if (!doReadNumber(&numberValue)) return false; + *value = v8::Date::New(numberValue); + return true; + } + + bool readNumber(v8::Handle<v8::Value>* value) + { double number; - char* numberAsByteArray = reinterpret_cast<char*>(&number); - for (unsigned i = 0; i < sizeof(double); ++i) - numberAsByteArray[i] = m_buffer[m_position++]; + if (!doReadNumber(&number)) + return false; *value = v8::Number::New(number); return true; } + bool readImageData(v8::Handle<v8::Value>* value) + { + uint32_t width; + uint32_t height; + uint32_t pixelDataLength; + if (!doReadUint32(&width)) + return false; + if (!doReadUint32(&height)) + return false; + if (!doReadUint32(&pixelDataLength)) + return false; + if (m_position + pixelDataLength > m_length) + return false; + PassRefPtr<ImageData> imageData = ImageData::create(width, height); + WTF::ByteArray* pixelArray = imageData->data()->data(); + ASSERT(pixelArray); + ASSERT(pixelArray->length() >= pixelDataLength); + memcpy(pixelArray->data(), m_buffer + m_position, pixelDataLength); + m_position += pixelDataLength; + *value = toV8(imageData); + return true; + } + + bool readBlob(v8::Handle<v8::Value>* value) + { + String path; + if (!readWebCoreString(&path)) + return false; + PassRefPtr<Blob> blob = Blob::create(path); + *value = toV8(blob); + return true; + } + + bool readFile(v8::Handle<v8::Value>* value) + { + String path; + if (!readWebCoreString(&path)) + return false; + PassRefPtr<File> file = File::create(path); + *value = toV8(file); + return true; + } + + bool readFileList(v8::Handle<v8::Value>* value) + { + uint32_t length; + if (!doReadUint32(&length)) + return false; + PassRefPtr<FileList> fileList = FileList::create(); + for (unsigned i = 0; i < length; ++i) { + String path; + if (!readWebCoreString(&path)) + return false; + fileList->append(File::create(path)); + } + *value = toV8(fileList); + return true; + } + bool doReadUint32(uint32_t* value) { *value = 0; - char currentByte; + uint8_t currentByte; int shift = 0; do { if (m_position >= m_length) @@ -579,64 +899,94 @@ private: return true; } - const char* m_buffer; + bool doReadNumber(double* number) + { + if (m_position + sizeof(double) > m_length) + return false; + uint8_t* numberAsByteArray = reinterpret_cast<uint8_t*>(number); + for (unsigned i = 0; i < sizeof(double); ++i) + numberAsByteArray[i] = m_buffer[m_position++]; + return true; + } + + const uint8_t* m_buffer; const unsigned m_length; unsigned m_position; }; -class Deserializer { +class Deserializer : public CompositeCreator { public: - explicit Deserializer(Reader& reader) : m_reader(reader) + explicit Deserializer(Reader& reader) + : m_reader(reader) { } - v8::Local<v8::Value> deserialize() + v8::Handle<v8::Value> deserialize() { v8::HandleScope scope; while (!m_reader.isEof()) { if (!doDeserialize()) - return v8::Local<v8::Value>(); + return v8::Null(); } if (stackDepth() != 1) - return v8::Local<v8::Value>(); + return v8::Null(); return scope.Close(element(0)); } + virtual bool createArray(uint32_t length, v8::Handle<v8::Value>* value) + { + if (length > stackDepth()) + return false; + v8::Local<v8::Array> array = v8::Array::New(length); + if (array.IsEmpty()) + return false; + const int depth = stackDepth() - length; + for (unsigned i = 0; i < length; ++i) + array->Set(i, element(depth + i)); + pop(length); + *value = array; + return true; + } + + virtual bool createObject(uint32_t numProperties, v8::Handle<v8::Value>* value) + { + v8::Local<v8::Object> object = v8::Object::New(); + if (object.IsEmpty()) + return false; + return initializeObject(object, numProperties, value); + } + + virtual bool createSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value) + { + v8::Local<v8::Array> array = v8::Array::New(length); + if (array.IsEmpty()) + return false; + return initializeObject(array, numProperties, value); + } + private: + bool initializeObject(v8::Handle<v8::Object> object, uint32_t numProperties, v8::Handle<v8::Value>* value) + { + unsigned length = 2 * numProperties; + if (length > stackDepth()) + return false; + for (unsigned i = stackDepth() - length; i < stackDepth(); i += 2) { + v8::Local<v8::Value> propertyName = element(i); + v8::Local<v8::Value> propertyValue = element(i + 1); + object->Set(propertyName, propertyValue); + } + pop(length); + *value = object; + return true; + } + bool doDeserialize() { - SerializationTag tag; v8::Local<v8::Value> value; - int length = 0; - if (!m_reader.read(&tag, &value, &length)) + if (!m_reader.read(&value, *this)) return false; - if (!value.IsEmpty()) { + if (!value.IsEmpty()) push(value); - } else if (tag == ObjectTag) { - if (length > stackDepth()) - return false; - v8::Local<v8::Object> object = v8::Object::New(); - for (int i = stackDepth() - length; i < stackDepth(); i += 2) { - v8::Local<v8::Value> propertyName = element(i); - v8::Local<v8::Value> propertyValue = element(i + 1); - object->Set(propertyName, propertyValue); - } - pop(length); - push(object); - } else if (tag == ArrayTag) { - if (length > stackDepth()) - return false; - v8::Local<v8::Array> array = v8::Array::New(length); - const int depth = stackDepth() - length; - { - v8::HandleScope scope; - for (int i = 0; i < length; ++i) - array->Set(v8::Integer::New(i), element(depth + i)); - } - pop(length); - push(array); - } else if (tag != PaddingTag) - return false; return true; } @@ -648,7 +998,7 @@ private: m_stack.shrink(m_stack.size() - length); } - int stackDepth() const { return m_stack.size(); } + unsigned stackDepth() const { return m_stack.size(); } v8::Local<v8::Value> element(unsigned index) { @@ -662,12 +1012,14 @@ private: } // namespace -SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value) +SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value, bool& didThrow) { + didThrow = false; Writer writer; Serializer serializer(writer); if (!serializer.serialize(value)) { - // FIXME: throw exception + throwError(NOT_SUPPORTED_ERR); + didThrow = true; return; } m_data = StringImpl::adopt(writer.data()); @@ -679,19 +1031,18 @@ SerializedScriptValue::SerializedScriptValue(String data, StringDataMode mode) m_data = data; else { ASSERT(mode == StringValue); - RefPtr<SharedBuffer> buffer = utf8Buffer(data); Writer writer; - writer.writeString(buffer->data(), buffer->size()); + writer.writeWebCoreString(data); m_data = StringImpl::adopt(writer.data()); } } -v8::Local<v8::Value> SerializedScriptValue::deserialize() +v8::Handle<v8::Value> SerializedScriptValue::deserialize() { if (!m_data.impl()) - return v8::Local<v8::Value>(); + return v8::Null(); COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes); - Reader reader(reinterpret_cast<const char*>(m_data.impl()->characters()), 2 * m_data.length()); + Reader reader(reinterpret_cast<const uint8_t*>(m_data.impl()->characters()), 2 * m_data.length()); Deserializer deserializer(reader); return deserializer.deserialize(); } diff --git a/WebCore/bindings/v8/SerializedScriptValue.h b/WebCore/bindings/v8/SerializedScriptValue.h index 7eb8935..8205a42 100644 --- a/WebCore/bindings/v8/SerializedScriptValue.h +++ b/WebCore/bindings/v8/SerializedScriptValue.h @@ -40,10 +40,36 @@ namespace WebCore { class SerializedScriptValue : public RefCounted<SerializedScriptValue> { public: + // Deserializes the given value and sets it as a property on the + // object. + static void deserializeAndSetProperty(v8::Handle<v8::Object> object, + const char* propertyName, + v8::PropertyAttribute attribute, + SerializedScriptValue* value) + { + if (!value) + return; + v8::Handle<v8::Value> deserialized = value->deserialize(); + object->ForceSet(v8::String::NewSymbol(propertyName), deserialized, attribute); + } + // Creates a serialized representation of the given V8 value. static PassRefPtr<SerializedScriptValue> create(v8::Handle<v8::Value> value) { - return adoptRef(new SerializedScriptValue(value)); + bool didThrow; + return adoptRef(new SerializedScriptValue(value, didThrow)); + } + + // Creates a serialized representation of the given V8 value. + // + // If a serialization error occurs (e.g., cyclic input value) this + // function returns an empty representation, schedules a V8 exception to + // be thrown using v8::ThrowException(), and sets |didThrow|. In this case + // the caller must not invoke any V8 operations until control returns to + // V8. When serialization is successful, |didThrow| is false. + static PassRefPtr<SerializedScriptValue> create(v8::Handle<v8::Value> value, bool& didThrow) + { + return adoptRef(new SerializedScriptValue(value, didThrow)); } // Creates a serialized value with the given data obtained from a @@ -74,9 +100,9 @@ public: String toWireString() const { return m_data; } - // Deserializes the value (in the current context). Returns an - // empty handle in case of failure. - v8::Local<v8::Value> deserialize(); + // Deserializes the value (in the current context). Returns a null value in + // case of failure. + v8::Handle<v8::Value> deserialize(); private: enum StringDataMode { @@ -86,7 +112,7 @@ private: SerializedScriptValue() { } - explicit SerializedScriptValue(v8::Handle<v8::Value>); + SerializedScriptValue(v8::Handle<v8::Value>, bool& didThrow); SerializedScriptValue(String data, StringDataMode mode); diff --git a/WebCore/bindings/v8/StaticDOMDataStore.cpp b/WebCore/bindings/v8/StaticDOMDataStore.cpp index 722051b..0b0d531 100644 --- a/WebCore/bindings/v8/StaticDOMDataStore.cpp +++ b/WebCore/bindings/v8/StaticDOMDataStore.cpp @@ -36,11 +36,11 @@ namespace WebCore { StaticDOMDataStore::StaticDOMDataStore(DOMData* domData) : DOMDataStore(domData) , m_staticDomNodeMap(&DOMDataStore::weakNodeCallback) - , m_staticDomObjectMap(domData, &DOMDataStore::weakDOMObjectCallback) - , m_staticActiveDomObjectMap(domData, &DOMDataStore::weakActiveDOMObjectCallback) + , m_staticDomObjectMap(&DOMDataStore::weakDOMObjectCallback) + , m_staticActiveDomObjectMap(&DOMDataStore::weakActiveDOMObjectCallback) #if ENABLE(SVG) - , m_staticDomSvgElementInstanceMap(domData, &DOMDataStore::weakSVGElementInstanceCallback) - , m_staticDomSvgObjectWithContextMap(domData, &DOMDataStore::weakSVGObjectWithContextCallback) + , m_staticDomSvgElementInstanceMap(&DOMDataStore::weakSVGElementInstanceCallback) + , m_staticDomSvgObjectWithContextMap(&DOMDataStore::weakSVGObjectWithContextCallback) #endif { m_domNodeMap = &m_staticDomNodeMap; diff --git a/WebCore/bindings/v8/StaticDOMDataStore.h b/WebCore/bindings/v8/StaticDOMDataStore.h index 64a90e0..d1e5a30 100644 --- a/WebCore/bindings/v8/StaticDOMDataStore.h +++ b/WebCore/bindings/v8/StaticDOMDataStore.h @@ -49,11 +49,11 @@ public: private: IntrusiveDOMWrapperMap m_staticDomNodeMap; - InternalDOMWrapperMap<void> m_staticDomObjectMap; - InternalDOMWrapperMap<void> m_staticActiveDomObjectMap; + DOMWrapperMap<void> m_staticDomObjectMap; + DOMWrapperMap<void> m_staticActiveDomObjectMap; #if ENABLE(SVG) - InternalDOMWrapperMap<SVGElementInstance> m_staticDomSvgElementInstanceMap; - InternalDOMWrapperMap<void> m_staticDomSvgObjectWithContextMap; + DOMWrapperMap<SVGElementInstance> m_staticDomSvgElementInstanceMap; + DOMWrapperMap<void> m_staticDomSvgObjectWithContextMap; #endif }; diff --git a/WebCore/bindings/v8/V8AbstractEventListener.cpp b/WebCore/bindings/v8/V8AbstractEventListener.cpp index 944fd57..6dc2b29 100644 --- a/WebCore/bindings/v8/V8AbstractEventListener.cpp +++ b/WebCore/bindings/v8/V8AbstractEventListener.cpp @@ -88,8 +88,6 @@ void V8AbstractEventListener::handleEvent(ScriptExecutionContext* context, Event v8::Handle<v8::Value> jsEvent = toV8(event); invokeEventHandler(context, event, jsEvent); - - Document::updateStyleForAllDocuments(); } void V8AbstractEventListener::disposeListenerObject() @@ -147,11 +145,8 @@ void V8AbstractEventListener::invokeEventHandler(ScriptExecutionContext* context if (!tryCatch.CanContinue()) return; - // If an error occurs while handling the event, it should be reported. - if (tryCatch.HasCaught()) { - reportException(0, tryCatch); - tryCatch.Reset(); - } + // If an error occurs while handling the event, it should be reported in a regular way. + tryCatch.Reset(); // Restore the old event. This must be done for all exit paths through this method. if (savedEvent.IsEmpty()) diff --git a/WebCore/bindings/v8/V8Binding.cpp b/WebCore/bindings/v8/V8Binding.cpp index 34020be..e0904d7 100644 --- a/WebCore/bindings/v8/V8Binding.cpp +++ b/WebCore/bindings/v8/V8Binding.cpp @@ -32,7 +32,6 @@ #include "V8Binding.h" #include "AtomicString.h" -#include "CString.h" #include "Element.h" #include "MathExtras.h" #include "PlatformString.h" @@ -43,6 +42,7 @@ #include "Threading.h" #include "V8Element.h" #include "V8Proxy.h" +#include <wtf/text/CString.h> #include <v8.h> @@ -174,6 +174,53 @@ int toInt32(v8::Handle<v8::Value> value, bool& ok) return intValue->Value(); } +uint32_t toUInt32(v8::Handle<v8::Value> value, bool& ok) +{ + ok = true; + + // FIXME: there is currently no Value::IsUint32(). This code does + // some contortions to avoid silently converting out-of-range + // values to uint32_t. + + // Fast case. The value is already a 32-bit positive integer. + if (value->IsInt32()) { + int32_t result = value->Int32Value(); + if (result >= 0) + return result; + } + + // Can the value be converted to a number? + v8::Local<v8::Number> numberObject = value->ToNumber(); + if (numberObject.IsEmpty()) { + ok = false; + return 0; + } + + // Does the value convert to nan or to an infinity? + double numberValue = numberObject->Value(); + if (isnan(numberValue) || isinf(numberValue)) { + ok = false; + return 0; + } + + // Can the value be converted to a 32-bit unsigned integer? + v8::Local<v8::Uint32> uintValue = value->ToUint32(); + if (uintValue.IsEmpty()) { + ok = false; + return 0; + } + + // FIXME: v8::Uint32::Value is not defined! + // http://code.google.com/p/v8/issues/detail?id=624 + v8::Local<v8::Int32> intValue = value->ToInt32(); + if (intValue.IsEmpty()) { + ok = false; + return 0; + } + + return static_cast<uint32_t>(intValue->Value()); +} + String toWebCoreString(const v8::Arguments& args, int index) { return v8ValueToWebCoreString(args[index]); } diff --git a/WebCore/bindings/v8/V8Binding.h b/WebCore/bindings/v8/V8Binding.h index 0be0ebd..696cd1a 100644 --- a/WebCore/bindings/v8/V8Binding.h +++ b/WebCore/bindings/v8/V8Binding.h @@ -108,6 +108,17 @@ namespace WebCore { return toInt32(value, ok); } + // Convert a value to a 32-bit unsigned integer. The conversion fails if the + // value cannot be converted to an unsigned integer or converts to nan or to an infinity. + uint32_t toUInt32(v8::Handle<v8::Value> value, bool& ok); + + // Convert a value to a 32-bit unsigned integer assuming the conversion cannot fail. + inline uint32_t toUInt32(v8::Handle<v8::Value> value) + { + bool ok; + return toUInt32(value, ok); + } + inline float toFloat(v8::Local<v8::Value> value) { return static_cast<float>(value->NumberValue()); diff --git a/WebCore/bindings/v8/V8Collection.h b/WebCore/bindings/v8/V8Collection.h index 9611571..1757c85 100644 --- a/WebCore/bindings/v8/V8Collection.h +++ b/WebCore/bindings/v8/V8Collection.h @@ -34,6 +34,7 @@ #include "HTMLFormElement.h" #include "HTMLSelectElement.h" #include "V8Binding.h" +#include "V8Node.h" #include "V8Proxy.h" #include <v8.h> @@ -63,7 +64,7 @@ template<class Collection, class ItemType> static v8::Handle<v8::Value> getNamed { // FIXME: assert object is a collection type ASSERT(V8DOMWrapper::maybeDOMWrapper(object)); - ASSERT(V8DOMWrapper::domWrapperType(object) != V8ClassIndex::NODE); + ASSERT(V8DOMWrapper::domWrapperType(object) != &V8Node::info); Collection* collection = toNativeCollection<Collection>(object); AtomicString propertyName = toAtomicWebCoreStringWithNullCheck(name); return getV8Object<ItemType>(collection->namedItem(propertyName)); @@ -89,7 +90,7 @@ template<class Collection, class ItemType> static v8::Handle<v8::Value> getIndex { // FIXME: Assert that object must be a collection type. ASSERT(V8DOMWrapper::maybeDOMWrapper(object)); - ASSERT(V8DOMWrapper::domWrapperType(object) != V8ClassIndex::NODE); + ASSERT(V8DOMWrapper::domWrapperType(object) != &V8Node::info); Collection* collection = toNativeCollection<Collection>(object); return getV8Object<ItemType>(collection->item(index)); } @@ -154,17 +155,16 @@ template<class Collection> static v8::Handle<v8::Value> collectionStringIndexedP // Add indexed getter to the function template for a collection. -template<class Collection, class ItemType> static void setCollectionIndexedGetter(v8::Handle<v8::FunctionTemplate> desc, V8ClassIndex::V8WrapperType type) +template<class Collection, class ItemType> static void setCollectionIndexedGetter(v8::Handle<v8::FunctionTemplate> desc) { - desc->InstanceTemplate()->SetIndexedPropertyHandler(collectionIndexedPropertyGetter<Collection, ItemType>, 0, 0, 0, collectionIndexedPropertyEnumerator<Collection>, - v8::Integer::New(V8ClassIndex::ToInt(type))); + desc->InstanceTemplate()->SetIndexedPropertyHandler(collectionIndexedPropertyGetter<Collection, ItemType>, 0, 0, 0, collectionIndexedPropertyEnumerator<Collection>); } // Add named getter to the function template for a collection. -template<class Collection, class ItemType> static void setCollectionNamedGetter(v8::Handle<v8::FunctionTemplate> desc, V8ClassIndex::V8WrapperType type) +template<class Collection, class ItemType> static void setCollectionNamedGetter(v8::Handle<v8::FunctionTemplate> desc) { - desc->InstanceTemplate()->SetNamedPropertyHandler(collectionNamedPropertyGetter<Collection, ItemType>, 0, 0, 0, 0, v8::Integer::New(V8ClassIndex::ToInt(type))); + desc->InstanceTemplate()->SetNamedPropertyHandler(collectionNamedPropertyGetter<Collection, ItemType>, 0, 0, 0, 0); } // Add indexed getter returning a string or null to a function template for a collection. diff --git a/WebCore/bindings/v8/V8DOMMap.cpp b/WebCore/bindings/v8/V8DOMMap.cpp index fa2fba3..b478d06 100644 --- a/WebCore/bindings/v8/V8DOMMap.cpp +++ b/WebCore/bindings/v8/V8DOMMap.cpp @@ -33,7 +33,6 @@ #include "DOMData.h" #include "DOMDataStore.h" -#include "DOMObjectsInclude.h" #include "MainThreadDOMData.h" #include "ScopedDOMDataStore.h" @@ -95,13 +94,10 @@ DOMWrapperMap<void>& getDOMSVGObjectWithContextMap() #endif // ENABLE(SVG) -static void removeAllDOMObjectsInCurrentThreadHelper() +void removeAllDOMObjectsInCurrentThread() { v8::HandleScope scope; - // Deref all objects in the delayed queue. - DOMData::getCurrent()->derefDelayedObjects(); - // The DOM objects with the following types only exist on the main thread. if (WTF::isMainThread()) { // Remove all DOM nodes. @@ -123,17 +119,6 @@ static void removeAllDOMObjectsInCurrentThreadHelper() DOMData::removeObjectsFromWrapperMap<void>(getActiveDOMObjectMap()); } -void removeAllDOMObjectsInCurrentThread() -{ - // Use the locker only if it has already been invoked before, as by worker thread. - if (v8::Locker::IsActive()) { - v8::Locker locker; - removeAllDOMObjectsInCurrentThreadHelper(); - } else - removeAllDOMObjectsInCurrentThreadHelper(); -} - - void visitDOMNodesInCurrentThread(DOMWrapperMap<Node>::Visitor* visitor) { v8::HandleScope scope; diff --git a/WebCore/bindings/v8/V8DOMWindowShell.cpp b/WebCore/bindings/v8/V8DOMWindowShell.cpp index cdf4393..6087479 100644 --- a/WebCore/bindings/v8/V8DOMWindowShell.cpp +++ b/WebCore/bindings/v8/V8DOMWindowShell.cpp @@ -31,12 +31,10 @@ #include "config.h" #include "V8DOMWindowShell.h" -#include "CString.h" #include "PlatformBridge.h" #include "CSSMutableStyleDeclaration.h" #include "DateExtension.h" #include "DocumentLoader.h" -#include "DOMObjectsInclude.h" #include "Frame.h" #include "FrameLoaderClient.h" #include "InspectorTimelineAgent.h" @@ -51,9 +49,9 @@ #include "V8DOMMap.h" #include "V8DOMWindow.h" #include "V8Document.h" +#include "V8GCForContextDispose.h" #include "V8HiddenPropertyName.h" #include "V8History.h" -#include "V8Index.h" #include "V8Location.h" #include "V8Proxy.h" #include "WorkerContextExecutionProxy.h" @@ -68,6 +66,7 @@ #include <wtf/StdLibExtras.h> #include <wtf/StringExtras.h> #include <wtf/UnusedParam.h> +#include <wtf/text/CString.h> #ifdef ANDROID_INSTRUMENT #include "TimeCounter.h" @@ -96,28 +95,20 @@ static void reportFatalErrorInV8(const char* location, const char* message) static Frame* getTargetFrame(v8::Local<v8::Object> host, v8::Local<v8::Value> data) { Frame* target = 0; - switch (V8ClassIndex::FromInt(data->Int32Value())) { - case V8ClassIndex::DOMWINDOW: { + WrapperTypeInfo* type = WrapperTypeInfo::unwrap(data); + if (V8DOMWindow::info.equals(type)) { v8::Handle<v8::Object> window = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), host); if (window.IsEmpty()) return target; DOMWindow* targetWindow = V8DOMWindow::toNative(window); target = targetWindow->frame(); - break; - } - case V8ClassIndex::LOCATION: { + } else if (V8History::info.equals(type)) { History* history = V8History::toNative(host); target = history->frame(); - break; - } - case V8ClassIndex::HISTORY: { + } else if (V8Location::info.equals(type)) { Location* location = V8Location::toNative(host); target = location->frame(); - break; - } - default: - break; } return target; } @@ -144,7 +135,6 @@ bool V8DOMWindowShell::isContextInitialized() // m_context, m_global, and m_wrapperBoilerplates should // all be non-empty if if m_context is non-empty. ASSERT(m_context.IsEmpty() || !m_global.IsEmpty()); - ASSERT(m_context.IsEmpty() || !m_wrapperBoilerplates.IsEmpty()); return !m_context.IsEmpty(); } @@ -154,15 +144,20 @@ void V8DOMWindowShell::disposeContextHandles() m_frame->loader()->client()->didDestroyScriptContextForFrame(); m_context.Dispose(); m_context.Clear(); + + // It's likely that disposing the context has created a lot of + // garbage. Notify V8 about this so it'll have a chance of cleaning + // it up when idle. + V8GCForContextDispose::instance().notifyContextDisposed(); } - if (!m_wrapperBoilerplates.IsEmpty()) { -#ifndef NDEBUG - V8GCController::unregisterGlobalHandle(this, m_wrapperBoilerplates); -#endif - m_wrapperBoilerplates.Dispose(); - m_wrapperBoilerplates.Clear(); + WrapperBoilerplateMap::iterator it = m_wrapperBoilerplates.begin(); + for (; it != m_wrapperBoilerplates.end(); ++it) { + v8::Persistent<v8::Object> wrapper = it->second; + wrapper.Dispose(); + wrapper.Clear(); } + m_wrapperBoilerplates.clear(); } void V8DOMWindowShell::destroyGlobal() @@ -299,19 +294,15 @@ void V8DOMWindowShell::initContextIfNeeded() #endif } - installHiddenObjectPrototype(v8Context); - m_wrapperBoilerplates = v8::Persistent<v8::Array>::New(v8::Array::New(V8ClassIndex::WRAPPER_TYPE_COUNT)); - // Bail out if allocation failed. - if (m_wrapperBoilerplates.IsEmpty()) { + if (!installHiddenObjectPrototype(v8Context)) { disposeContextHandles(); return; } -#ifndef NDEBUG - V8GCController::registerGlobalHandle(PROXY, this, m_wrapperBoilerplates); -#endif - if (!installDOMWindow(v8Context, m_frame->domWindow())) + if (!installDOMWindow(v8Context, m_frame->domWindow())) { disposeContextHandles(); + return; + } updateDocument(); @@ -357,7 +348,7 @@ v8::Persistent<v8::Context> V8DOMWindowShell::createNewContext(v8::Handle<v8::Ob // Note: we check the loader URL here instead of the document URL // because we might be currently loading an URL into a blank page. // See http://code.google.com/p/chromium/issues/detail?id=10924 - if (extensions[i].scheme.length() > 0 && (extensions[i].scheme != m_frame->loader()->activeDocumentLoader()->url().protocol() || extensions[i].scheme != m_frame->page()->mainFrame()->loader()->activeDocumentLoader()->url().protocol())) + if (extensions[i].scheme.length() > 0 && (extensions[i].scheme != m_frame->loader()->activeDocumentLoader()->url().protocol())) continue; extensionNames[index++] = extensions[i].extension->name(); @@ -369,6 +360,7 @@ v8::Persistent<v8::Context> V8DOMWindowShell::createNewContext(v8::Handle<v8::Ob } void V8DOMWindowShell::setContext(v8::Handle<v8::Context> context) +<<<<<<< HEAD { // if we already have a context, clear it before setting the new one. if (!m_context.IsEmpty()) { @@ -379,29 +371,37 @@ void V8DOMWindowShell::setContext(v8::Handle<v8::Context> context) } bool V8DOMWindowShell::installDOMWindow(v8::Handle<v8::Context> context, DOMWindow* window) +======= +>>>>>>> webkit.org at r58033 { - v8::Handle<v8::String> implicitProtoString = v8::String::New("__proto__"); - if (implicitProtoString.IsEmpty()) - return false; + // if we already have a context, clear it before setting the new one. + if (!m_context.IsEmpty()) { + m_context.Dispose(); + m_context.Clear(); + } + m_context = v8::Persistent<v8::Context>::New(context); +} +bool V8DOMWindowShell::installDOMWindow(v8::Handle<v8::Context> context, DOMWindow* window) +{ // Create a new JS window object and use it as the prototype for the shadow global object. - v8::Handle<v8::Function> windowConstructor = V8DOMWrapper::getConstructor(V8ClassIndex::DOMWINDOW, getHiddenObjectPrototype(context)); + v8::Handle<v8::Function> windowConstructor = V8DOMWrapper::getConstructor(&V8DOMWindow::info, getHiddenObjectPrototype(context)); v8::Local<v8::Object> jsWindow = SafeAllocation::newInstance(windowConstructor); // Bail out if allocation failed. if (jsWindow.IsEmpty()) return false; // Wrap the window. - V8DOMWrapper::setDOMWrapper(jsWindow, V8ClassIndex::ToInt(V8ClassIndex::DOMWINDOW), window); - V8DOMWrapper::setDOMWrapper(v8::Handle<v8::Object>::Cast(jsWindow->GetPrototype()), V8ClassIndex::ToInt(V8ClassIndex::DOMWINDOW), window); + V8DOMWrapper::setDOMWrapper(jsWindow, &V8DOMWindow::info, window); + V8DOMWrapper::setDOMWrapper(v8::Handle<v8::Object>::Cast(jsWindow->GetPrototype()), &V8DOMWindow::info, window); window->ref(); V8DOMWrapper::setJSWrapperForDOMObject(window, v8::Persistent<v8::Object>::New(jsWindow)); // Insert the window instance as the prototype of the shadow object. - v8::Handle<v8::Object> v8Global = context->Global(); - V8DOMWrapper::setDOMWrapper(v8::Handle<v8::Object>::Cast(v8Global->GetPrototype()), V8ClassIndex::ToInt(V8ClassIndex::DOMWINDOW), window); - v8Global->Set(implicitProtoString, jsWindow); + v8::Handle<v8::Object> v8RealGlobal = v8::Handle<v8::Object>::Cast(context->Global()->GetPrototype()); + V8DOMWrapper::setDOMWrapper(v8RealGlobal, &V8DOMWindow::info, window); + v8RealGlobal->SetPrototype(jsWindow); return true; } @@ -533,31 +533,38 @@ v8::Handle<v8::Value> V8DOMWindowShell::getHiddenObjectPrototype(v8::Handle<v8:: return context->Global()->GetHiddenValue(V8HiddenPropertyName::objectPrototype()); } -void V8DOMWindowShell::installHiddenObjectPrototype(v8::Handle<v8::Context> context) +bool V8DOMWindowShell::installHiddenObjectPrototype(v8::Handle<v8::Context> context) { v8::Handle<v8::String> objectString = v8::String::New("Object"); v8::Handle<v8::String> prototypeString = v8::String::New("prototype"); v8::Handle<v8::String> hiddenObjectPrototypeString = V8HiddenPropertyName::objectPrototype(); // Bail out if allocation failed. if (objectString.IsEmpty() || prototypeString.IsEmpty() || hiddenObjectPrototypeString.IsEmpty()) - return; + return false; v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(context->Global()->Get(objectString)); + // Bail out if fetching failed. + if (object.IsEmpty()) + return false; v8::Handle<v8::Value> objectPrototype = object->Get(prototypeString); + // Bail out if fetching failed. + if (objectPrototype.IsEmpty()) + return false; context->Global()->SetHiddenValue(hiddenObjectPrototypeString, objectPrototype); + + return true; } -v8::Local<v8::Object> V8DOMWindowShell::createWrapperFromCacheSlowCase(V8ClassIndex::V8WrapperType type) +v8::Local<v8::Object> V8DOMWindowShell::createWrapperFromCacheSlowCase(WrapperTypeInfo* type) { // Not in cache. - int classIndex = V8ClassIndex::ToInt(type); initContextIfNeeded(); v8::Context::Scope scope(m_context); v8::Local<v8::Function> function = V8DOMWrapper::getConstructor(type, getHiddenObjectPrototype(m_context)); v8::Local<v8::Object> instance = SafeAllocation::newInstance(function); if (!instance.IsEmpty()) { - m_wrapperBoilerplates->Set(v8::Integer::New(classIndex), instance); + m_wrapperBoilerplates.set(type, v8::Persistent<v8::Object>::New(instance)); return instance->Clone(); } return notHandledByInterceptor(); diff --git a/WebCore/bindings/v8/V8DOMWindowShell.h b/WebCore/bindings/v8/V8DOMWindowShell.h index 6b8952d..f4eaff2 100644 --- a/WebCore/bindings/v8/V8DOMWindowShell.h +++ b/WebCore/bindings/v8/V8DOMWindowShell.h @@ -31,7 +31,8 @@ #ifndef V8DOMWindowShell_h #define V8DOMWindowShell_h -#include "V8Index.h" +#include "WrapperTypeInfo.h" +#include <wtf/HashMap.h> #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> #include <wtf/RefPtr.h> @@ -73,16 +74,15 @@ public: static v8::Handle<v8::Value> getHiddenObjectPrototype(v8::Handle<v8::Context>); // WARNING: Call |installHiddenObjectPrototype| only on fresh contexts! - static void installHiddenObjectPrototype(v8::Handle<v8::Context>); + static bool installHiddenObjectPrototype(v8::Handle<v8::Context>); // To create JS Wrapper objects, we create a cache of a 'boiler plate' // object, and then simply Clone that object each time we need a new one. // This is faster than going through the full object creation process. - v8::Local<v8::Object> createWrapperFromCache(V8ClassIndex::V8WrapperType type) + v8::Local<v8::Object> createWrapperFromCache(WrapperTypeInfo* type) { - int classIndex = V8ClassIndex::ToInt(type); - v8::Local<v8::Object> clone(m_wrapperBoilerplates->CloneElementAt(classIndex)); - return clone.IsEmpty() ? createWrapperFromCacheSlowCase(type) : clone; + v8::Persistent<v8::Object> boilerplate = m_wrapperBoilerplates.get(type); + return boilerplate.IsEmpty() ? createWrapperFromCacheSlowCase(type) : boilerplate->Clone(); } static void setLocation(DOMWindow*, const String& relativeURL); @@ -102,15 +102,14 @@ private: void updateDocumentWrapperCache(); void clearDocumentWrapperCache(); - v8::Local<v8::Object> createWrapperFromCacheSlowCase(V8ClassIndex::V8WrapperType); + v8::Local<v8::Object> createWrapperFromCacheSlowCase(WrapperTypeInfo*); Frame* m_frame; // For each possible type of wrapper, we keep a boilerplate object. - // The boilerplate is used to create additional wrappers of the same - // type. We keep a single persistent handle to an array of the - // activated boilerplates. - v8::Persistent<v8::Array> m_wrapperBoilerplates; + // The boilerplate is used to create additional wrappers of the same type. + typedef WTF::HashMap<WrapperTypeInfo*, v8::Persistent<v8::Object> > WrapperBoilerplateMap; + WrapperBoilerplateMap m_wrapperBoilerplates; v8::Persistent<v8::Context> m_context; v8::Persistent<v8::Object> m_global; diff --git a/WebCore/bindings/v8/V8DOMWrapper.cpp b/WebCore/bindings/v8/V8DOMWrapper.cpp index cf11e6c..ac29170 100644 --- a/WebCore/bindings/v8/V8DOMWrapper.cpp +++ b/WebCore/bindings/v8/V8DOMWrapper.cpp @@ -1,10 +1,10 @@ /* * Copyright (C) 2009 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 @@ -14,7 +14,7 @@ * * 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 @@ -33,44 +33,50 @@ #include "CSSMutableStyleDeclaration.h" #include "DOMDataStore.h" -#include "DOMObjectsInclude.h" #include "DocumentLoader.h" #include "FrameLoaderClient.h" #include "Notification.h" -#include "SVGElementInstance.h" -#include "SVGPathSeg.h" #include "ScriptController.h" #include "V8AbstractEventListener.h" #include "V8Binding.h" #include "V8Collection.h" #include "V8CustomEventListener.h" +#include "V8DedicatedWorkerContext.h" #include "V8DOMApplicationCache.h" #include "V8DOMMap.h" #include "V8DOMWindow.h" #include "V8EventListenerList.h" +#include "V8EventSource.h" #include "V8HTMLCollection.h" #include "V8HTMLDocument.h" -#include "V8Index.h" #include "V8IsolatedContext.h" #include "V8Location.h" #include "V8MessageChannel.h" #include "V8NamedNodeMap.h" #include "V8Node.h" +#include "V8NodeFilterCondition.h" #include "V8NodeList.h" #include "V8Notification.h" #include "V8Proxy.h" -#include "V8SVGElementInstance.h" #include "V8SharedWorker.h" #include "V8SharedWorkerContext.h" #include "V8StyleSheet.h" #include "V8WebSocket.h" #include "V8Worker.h" #include "V8WorkerContext.h" +#include "V8WorkerContextEventListener.h" #include "V8XMLHttpRequest.h" #include "WebGLArray.h" #include "WebGLContextAttributes.h" #include "WebGLUniformLocation.h" #include "WorkerContextExecutionProxy.h" +#include "WrapperTypeInfo.h" + +#if ENABLE(SVG) +#include "SVGElementInstance.h" +#include "SVGPathSeg.h" +#include "V8SVGElementInstance.h" +#endif #include <algorithm> #include <utility> @@ -86,60 +92,11 @@ namespace WebCore { typedef HashMap<Node*, v8::Object*> DOMNodeMap; typedef HashMap<void*, v8::Object*> DOMObjectMap; -#if ENABLE(3D_CANVAS) -void V8DOMWrapper::setIndexedPropertiesToExternalArray(v8::Handle<v8::Object> wrapper, - int index, - void* address, - int length) -{ - v8::ExternalArrayType array_type = v8::kExternalByteArray; - V8ClassIndex::V8WrapperType classIndex = V8ClassIndex::FromInt(index); - switch (classIndex) { - case V8ClassIndex::WEBGLBYTEARRAY: - array_type = v8::kExternalByteArray; - break; - case V8ClassIndex::WEBGLUNSIGNEDBYTEARRAY: - array_type = v8::kExternalUnsignedByteArray; - break; - case V8ClassIndex::WEBGLSHORTARRAY: - array_type = v8::kExternalShortArray; - break; - case V8ClassIndex::WEBGLUNSIGNEDSHORTARRAY: - array_type = v8::kExternalUnsignedShortArray; - break; - case V8ClassIndex::WEBGLINTARRAY: - array_type = v8::kExternalIntArray; - break; - case V8ClassIndex::WEBGLUNSIGNEDINTARRAY: - array_type = v8::kExternalUnsignedIntArray; - break; - case V8ClassIndex::WEBGLFLOATARRAY: - array_type = v8::kExternalFloatArray; - break; - default: - ASSERT_NOT_REACHED(); - } - wrapper->SetIndexedPropertiesToExternalArrayData(address, - array_type, - length); -} -#endif - // The caller must have increased obj's ref count. void V8DOMWrapper::setJSWrapperForDOMObject(void* object, v8::Persistent<v8::Object> wrapper) { ASSERT(V8DOMWrapper::maybeDOMWrapper(wrapper)); -#ifndef NDEBUG - V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(wrapper); - switch (type) { -#define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE: - ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE) - ASSERT_NOT_REACHED(); -#undef MAKE_CASE - default: - break; - } -#endif + ASSERT(!domWrapperType(wrapper)->toActiveDOMObjectFunction); getDOMObjectMap().set(object, wrapper); } @@ -147,16 +104,7 @@ void V8DOMWrapper::setJSWrapperForDOMObject(void* object, v8::Persistent<v8::Obj void V8DOMWrapper::setJSWrapperForActiveDOMObject(void* object, v8::Persistent<v8::Object> wrapper) { ASSERT(V8DOMWrapper::maybeDOMWrapper(wrapper)); -#ifndef NDEBUG - V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(wrapper); - switch (type) { -#define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE: break; - ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE) - default: - ASSERT_NOT_REACHED(); -#undef MAKE_CASE - } -#endif + ASSERT(domWrapperType(wrapper)->toActiveDOMObjectFunction); getActiveDOMObjectMap().set(object, wrapper); } @@ -167,7 +115,7 @@ void V8DOMWrapper::setJSWrapperForDOMNode(Node* node, v8::Persistent<v8::Object> getDOMNodeMap().set(node, wrapper); } -v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Value> objectPrototype) +v8::Local<v8::Function> V8DOMWrapper::getConstructor(WrapperTypeInfo* type, v8::Handle<v8::Value> objectPrototype) { // A DOM constructor is a function instance created from a DOM constructor // template. There is one instance per context. A DOM constructor is @@ -178,7 +126,7 @@ v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType // The reason for 2) is that, in Safari, a DOM constructor is a normal JS // object, but not a function. Hotmail relies on the fact that, in Safari, // HTMLElement.__proto__ == Object.prototype. - v8::Handle<v8::FunctionTemplate> functionTemplate = V8ClassIndex::getTemplate(type); + v8::Handle<v8::FunctionTemplate> functionTemplate = type->getTemplate(); // Getting the function might fail if we're running out of // stack or memory. v8::TryCatch tryCatch; @@ -187,11 +135,11 @@ v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType return v8::Local<v8::Function>(); // Hotmail fix, see comments above. if (!objectPrototype.IsEmpty()) - value->Set(v8::String::New("__proto__"), objectPrototype); + value->SetPrototype(objectPrototype); return value; } -v8::Local<v8::Function> V8DOMWrapper::getConstructorForContext(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Context> context) +v8::Local<v8::Function> V8DOMWrapper::getConstructorForContext(WrapperTypeInfo* type, v8::Handle<v8::Context> context) { // Enter the scope for this context to get the correct constructor. v8::Context::Scope scope(context); @@ -199,7 +147,7 @@ v8::Local<v8::Function> V8DOMWrapper::getConstructorForContext(V8ClassIndex::V8W return getConstructor(type, V8DOMWindowShell::getHiddenObjectPrototype(context)); } -v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType type, DOMWindow* window) +v8::Local<v8::Function> V8DOMWrapper::getConstructor(WrapperTypeInfo* type, DOMWindow* window) { Frame* frame = window->frame(); if (!frame) @@ -213,9 +161,14 @@ v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType } #if ENABLE(WORKERS) +<<<<<<< HEAD v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType type, WorkerContext*) +======= +v8::Local<v8::Function> V8DOMWrapper::getConstructor(WrapperTypeInfo* type, WorkerContext*) +>>>>>>> webkit.org at r58033 { - WorkerContextExecutionProxy* proxy = WorkerContextExecutionProxy::retrieve(); + WorkerScriptController* controller = WorkerScriptController::controllerForContext(); + WorkerContextExecutionProxy* proxy = controller ? controller->proxy() : 0; if (!proxy) return v8::Local<v8::Function>(); @@ -226,8 +179,22 @@ v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType return getConstructorForContext(type, context); } #endif +<<<<<<< HEAD +======= -void V8DOMWrapper::setHiddenWindowReference(Frame* frame, const int internalIndex, v8::Handle<v8::Object> jsObject) +void V8DOMWrapper::setHiddenReference(v8::Handle<v8::Object> parent, v8::Handle<v8::Value> child) +{ + v8::Local<v8::Value> hiddenReferenceObject = parent->GetInternalField(v8DOMHiddenReferenceArrayIndex); + if (hiddenReferenceObject->IsNull() || hiddenReferenceObject->IsUndefined()) { + hiddenReferenceObject = v8::Array::New(); + parent->SetInternalField(v8DOMHiddenReferenceArrayIndex, hiddenReferenceObject); + } + v8::Local<v8::Array> hiddenReferenceArray = v8::Local<v8::Array>::Cast(hiddenReferenceObject); + hiddenReferenceArray->Set(v8::Integer::New(hiddenReferenceArray->Length()), child); +} +>>>>>>> webkit.org at r58033 + +void V8DOMWrapper::setHiddenWindowReference(Frame* frame, v8::Handle<v8::Value> jsObject) { // Get DOMWindow if (!frame) @@ -236,21 +203,18 @@ void V8DOMWrapper::setHiddenWindowReference(Frame* frame, const int internalInde if (context.IsEmpty()) return; - ASSERT(internalIndex < V8DOMWindow::internalFieldCount); - v8::Handle<v8::Object> global = context->Global(); // Look for real DOM wrapper. global = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), global); ASSERT(!global.IsEmpty()); - ASSERT(global->GetInternalField(internalIndex)->IsUndefined()); - global->SetInternalField(internalIndex, jsObject); + + setHiddenReference(global, jsObject); } -V8ClassIndex::V8WrapperType V8DOMWrapper::domWrapperType(v8::Handle<v8::Object> object) +WrapperTypeInfo* V8DOMWrapper::domWrapperType(v8::Handle<v8::Object> object) { ASSERT(V8DOMWrapper::maybeDOMWrapper(object)); - v8::Handle<v8::Value> type = object->GetInternalField(v8DOMWrapperTypeIndex); - return V8ClassIndex::FromInt(type->Int32Value()); + return static_cast<WrapperTypeInfo*>(object->GetPointerFromInternalField(v8DOMWrapperTypeIndex)); } PassRefPtr<NodeFilter> V8DOMWrapper::wrapNativeNodeFilter(v8::Handle<v8::Value> filter) @@ -275,15 +239,24 @@ static bool globalObjectPrototypeIsDOMWindow(v8::Handle<v8::Object> objectProtot #if ENABLE(SHARED_WORKERS) // We can identify what type of context the global object is wrapping by looking at the // internal field count of its prototype. This assumes WorkerContexts and DOMWindows have different numbers - // of internal fields, so a COMPILE_ASSERT is included to warn if this ever changes. DOMWindow has - // traditionally had far more internal fields than any other class. - COMPILE_ASSERT(V8DOMWindow::internalFieldCount != V8WorkerContext::internalFieldCount && V8DOMWindow::internalFieldCount != V8SharedWorkerContext::internalFieldCount, + // of internal fields, so a COMPILE_ASSERT is included to warn if this ever changes. +#if ENABLE(WORKERS) + COMPILE_ASSERT(V8DOMWindow::internalFieldCount != V8WorkerContext::internalFieldCount, DOMWindowAndWorkerContextHaveUnequalFieldCounts); +<<<<<<< HEAD +======= + COMPILE_ASSERT(V8DOMWindow::internalFieldCount != V8DedicatedWorkerContext::internalFieldCount, + DOMWindowAndDedicatedWorkerContextHaveUnequalFieldCounts); +#endif +#if ENABLE(SHARED_WORKERS) + COMPILE_ASSERT(V8DOMWindow::internalFieldCount != V8SharedWorkerContext::internalFieldCount, + DOMWindowAndSharedWorkerContextHaveUnequalFieldCounts); +>>>>>>> webkit.org at r58033 #endif return objectPrototype->InternalFieldCount() == V8DOMWindow::internalFieldCount; } -v8::Local<v8::Object> V8DOMWrapper::instantiateV8Object(V8Proxy* proxy, V8ClassIndex::V8WrapperType type, void* impl) +v8::Local<v8::Object> V8DOMWrapper::instantiateV8Object(V8Proxy* proxy, WrapperTypeInfo* type, void* impl) { WorkerContext* workerContext = 0; if (V8IsolatedContext::getEntered()) { @@ -316,12 +289,16 @@ v8::Local<v8::Object> V8DOMWrapper::instantiateV8Object(V8Proxy* proxy, V8ClassI function = getConstructor(type, workerContext); else #endif +<<<<<<< HEAD function = V8ClassIndex::getTemplate(type)->GetFunction(); +======= + function = type->getTemplate()->GetFunction(); +>>>>>>> webkit.org at r58033 instance = SafeAllocation::newInstance(function); } if (!instance.IsEmpty()) { // Avoid setting the DOM wrapper for failed allocations. - setDOMWrapper(instance, V8ClassIndex::ToInt(type), impl); + setDOMWrapper(instance, type, impl); } return instance; } @@ -338,10 +315,6 @@ bool V8DOMWrapper::maybeDOMWrapper(v8::Handle<v8::Value> value) ASSERT(object->InternalFieldCount() >= v8DefaultWrapperInternalFieldCount); - v8::Handle<v8::Value> type = object->GetInternalField(v8DOMWrapperTypeIndex); - ASSERT(type->IsInt32()); - ASSERT(V8ClassIndex::INVALID_CLASS_INDEX < type->Int32Value() && type->Int32Value() < V8ClassIndex::CLASSINDEX_END); - v8::Handle<v8::Value> wrapper = object->GetInternalField(v8DOMWrapperObjectIndex); ASSERT(wrapper->IsNumber() || wrapper->IsExternal()); @@ -356,7 +329,7 @@ bool V8DOMWrapper::isValidDOMObject(v8::Handle<v8::Value> value) return v8::Handle<v8::Object>::Cast(value)->InternalFieldCount(); } -bool V8DOMWrapper::isWrapperOfType(v8::Handle<v8::Value> value, V8ClassIndex::V8WrapperType classType) +bool V8DOMWrapper::isWrapperOfType(v8::Handle<v8::Value> value, WrapperTypeInfo* type) { if (!isValidDOMObject(value)) return false; @@ -367,11 +340,8 @@ bool V8DOMWrapper::isWrapperOfType(v8::Handle<v8::Value> value, V8ClassIndex::V8 v8::Handle<v8::Value> wrapper = object->GetInternalField(v8DOMWrapperObjectIndex); ASSERT(wrapper->IsNumber() || wrapper->IsExternal()); - v8::Handle<v8::Value> type = object->GetInternalField(v8DOMWrapperTypeIndex); - ASSERT(type->IsInt32()); - ASSERT(V8ClassIndex::INVALID_CLASS_INDEX < type->Int32Value() && type->Int32Value() < V8ClassIndex::CLASSINDEX_END); - - return V8ClassIndex::FromInt(type->Int32Value()) == classType; + WrapperTypeInfo* typeInfo = static_cast<WrapperTypeInfo*>(object->GetPointerFromInternalField(v8DOMWrapperTypeIndex)); + return typeInfo == type; } v8::Handle<v8::Object> V8DOMWrapper::getWrapper(Node* node) @@ -440,9 +410,6 @@ v8::Handle<v8::Value> V8DOMWrapper::convertEventTargetToV8Object(EventTarget* ta return wrapper; } - if (XMLHttpRequest* xhr = target->toXMLHttpRequest()) - return toV8(xhr); - // MessagePort is created within its JS counterpart if (MessagePort* port = target->toMessagePort()) { v8::Handle<v8::Object> wrapper = getActiveDOMObjectMap().get(port); @@ -470,6 +437,7 @@ v8::Handle<v8::Value> V8DOMWrapper::convertEventTargetToV8Object(EventTarget* ta return notHandledByInterceptor(); } +<<<<<<< HEAD PassRefPtr<EventListener> V8DOMWrapper::getEventListener(Node* node, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) { return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute); @@ -530,37 +498,23 @@ PassRefPtr<EventListener> V8DOMWrapper::getEventListener(XMLHttpRequestUpload* u #if ENABLE(EVENTSOURCE) PassRefPtr<EventListener> V8DOMWrapper::getEventListener(EventSource* eventSource, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) +======= +PassRefPtr<EventListener> V8DOMWrapper::getEventListener(v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) +>>>>>>> webkit.org at r58033 { - if (V8Proxy::retrieve(eventSource->scriptExecutionContext())) - return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute); - + v8::Handle<v8::Context> context = v8::Context::GetCurrent(); + if (context.IsEmpty()) + return 0; + if (lookup == ListenerFindOnly) + return V8EventListenerList::findWrapper(value, isAttribute); + v8::Handle<v8::Object> globalPrototype = v8::Handle<v8::Object>::Cast(context->Global()->GetPrototype()); + if (globalObjectPrototypeIsDOMWindow(globalPrototype)) + return V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute); #if ENABLE(WORKERS) - WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); - if (workerContextProxy) - return workerContextProxy->findOrCreateEventListener(value, isAttribute, lookup == ListenerFindOnly); -#endif - + return V8EventListenerList::findOrCreateWrapper<V8WorkerContextEventListener>(value, isAttribute); +#else return 0; -} #endif - -PassRefPtr<EventListener> V8DOMWrapper::getEventListener(EventTarget* eventTarget, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) -{ - if (V8Proxy::retrieve(eventTarget->scriptExecutionContext())) - return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute); - -#if ENABLE(WORKERS) - WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); - if (workerContextProxy) - return workerContextProxy->findOrCreateEventListener(value, isAttribute, lookup == ListenerFindOnly); -#endif - - return 0; -} - -PassRefPtr<EventListener> V8DOMWrapper::getEventListener(V8Proxy* proxy, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) -{ - return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute); } } // namespace WebCore diff --git a/WebCore/bindings/v8/V8DOMWrapper.h b/WebCore/bindings/v8/V8DOMWrapper.h index 8a3fa3f..97e269a 100644 --- a/WebCore/bindings/v8/V8DOMWrapper.h +++ b/WebCore/bindings/v8/V8DOMWrapper.h @@ -39,62 +39,19 @@ #include "V8CustomXPathNSResolver.h" #include "V8DOMMap.h" #include "V8Event.h" -#include "V8Index.h" #include "V8Utilities.h" #include "V8XPathNSResolver.h" +#include "WrapperTypeInfo.h" #include "XPathNSResolver.h" #include <v8.h> namespace WebCore { - // FIXME: This probably aren't all needed. - class CSSRule; - class CSSRuleList; - class CSSStyleDeclaration; - class CSSValue; - class CSSValueList; - class ClientRectList; - class DOMImplementation; class DOMWindow; - class Document; - class Element; - class Event; - class EventListener; class EventTarget; class Frame; - class HTMLCollection; - class HTMLDocument; - class HTMLElement; - class HTMLOptionsCollection; - class MediaList; - class MimeType; - class MimeTypeArray; - class NamedNodeMap; - class Navigator; class Node; - class NodeFilter; - class NodeList; - class Plugin; - class PluginArray; - class SVGElement; -#if ENABLE(SVG) - class SVGElementInstance; -#endif - class Screen; - class ScriptExecutionContext; -#if ENABLE(DOM_STORAGE) - class Storage; - class StorageEvent; -#endif - class String; - class StyleSheet; - class StyleSheetList; - class V8EventListener; - class V8ObjectEventListener; class V8Proxy; -#if ENABLE(WEB_SOCKETS) - class WebSocket; -#endif class WorkerContext; enum ListenerLookupType { @@ -110,11 +67,11 @@ namespace WebCore { #endif // Sets contents of a DOM wrapper. - static void setDOMWrapper(v8::Handle<v8::Object> object, int type, void* cptr) + static void setDOMWrapper(v8::Handle<v8::Object> object, WrapperTypeInfo* type, void* cptr) { ASSERT(object->InternalFieldCount() >= 2); object->SetPointerInInternalField(v8DOMWrapperObjectIndex, cptr); - object->SetInternalField(v8DOMWrapperTypeIndex, v8::Integer::New(type)); + object->SetPointerInInternalField(v8DOMWrapperTypeIndex, type); } static v8::Handle<v8::Object> lookupDOMWrapper(v8::Handle<v8::FunctionTemplate> functionTemplate, v8::Handle<v8::Object> object) @@ -122,7 +79,7 @@ namespace WebCore { return object.IsEmpty() ? object : object->FindInstanceInPrototypeChain(functionTemplate); } - static V8ClassIndex::V8WrapperType domWrapperType(v8::Handle<v8::Object>); + static WrapperTypeInfo* domWrapperType(v8::Handle<v8::Object>); static v8::Handle<v8::Value> convertEventTargetToV8Object(PassRefPtr<EventTarget> eventTarget) { @@ -131,27 +88,7 @@ namespace WebCore { static v8::Handle<v8::Value> convertEventTargetToV8Object(EventTarget*); - static PassRefPtr<EventListener> getEventListener(Node* node, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup); - - static PassRefPtr<EventListener> getEventListener(SVGElementInstance* element, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup); - - static PassRefPtr<EventListener> getEventListener(AbstractWorker* worker, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup); - -#if ENABLE(NOTIFICATIONS) - static PassRefPtr<EventListener> getEventListener(Notification* notification, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup); -#endif - - static PassRefPtr<EventListener> getEventListener(WorkerContext* workerContext, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup); - - static PassRefPtr<EventListener> getEventListener(XMLHttpRequestUpload* upload, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup); - -#if ENABLE(EVENTSOURCE) - static PassRefPtr<EventListener> getEventListener(EventSource* eventTarget, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup); -#endif - - static PassRefPtr<EventListener> getEventListener(EventTarget* eventTarget, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup); - - static PassRefPtr<EventListener> getEventListener(V8Proxy* proxy, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup); + static PassRefPtr<EventListener> getEventListener(v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup); #if ENABLE(XPATH) // XPath-related utilities @@ -161,7 +98,7 @@ namespace WebCore { if (V8XPathNSResolver::HasInstance(value)) resolver = V8XPathNSResolver::toNative(v8::Handle<v8::Object>::Cast(value)); else if (value->IsObject()) - resolver = V8CustomXPathNSResolver::create(proxy, value->ToObject()); + resolver = V8CustomXPathNSResolver::create(value->ToObject()); return resolver; } #endif @@ -169,10 +106,12 @@ namespace WebCore { // Wrap JS node filter in C++. static PassRefPtr<NodeFilter> wrapNativeNodeFilter(v8::Handle<v8::Value>); - static v8::Local<v8::Function> getConstructorForContext(V8ClassIndex::V8WrapperType, v8::Handle<v8::Context>); - static v8::Local<v8::Function> getConstructor(V8ClassIndex::V8WrapperType, v8::Handle<v8::Value> objectPrototype); - static v8::Local<v8::Function> getConstructor(V8ClassIndex::V8WrapperType, DOMWindow*); - static v8::Local<v8::Function> getConstructor(V8ClassIndex::V8WrapperType, WorkerContext*); + static v8::Local<v8::Function> getConstructorForContext(WrapperTypeInfo*, v8::Handle<v8::Context>); + static v8::Local<v8::Function> getConstructor(WrapperTypeInfo*, v8::Handle<v8::Value> objectPrototype); + static v8::Local<v8::Function> getConstructor(WrapperTypeInfo*, DOMWindow*); +#if ENABLE(WORKERS) + static v8::Local<v8::Function> getConstructor(WrapperTypeInfo*, WorkerContext*); +#endif // Set JS wrapper of a DOM object, the caller in charge of increase ref. static void setJSWrapperForDOMObject(void*, v8::Persistent<v8::Object>); @@ -182,18 +121,14 @@ namespace WebCore { static bool isValidDOMObject(v8::Handle<v8::Value>); // Check whether a V8 value is a wrapper of type |classType|. - static bool isWrapperOfType(v8::Handle<v8::Value>, V8ClassIndex::V8WrapperType); + static bool isWrapperOfType(v8::Handle<v8::Value>, WrapperTypeInfo*); + + static void setHiddenReference(v8::Handle<v8::Object> parent, v8::Handle<v8::Value> child); -#if ENABLE(3D_CANVAS) - static void setIndexedPropertiesToExternalArray(v8::Handle<v8::Object>, - int, - void*, - int); -#endif // Set hidden references in a DOMWindow object of a frame. - static void setHiddenWindowReference(Frame*, const int internalIndex, v8::Handle<v8::Object>); + static void setHiddenWindowReference(Frame*, v8::Handle<v8::Value>); - static v8::Local<v8::Object> instantiateV8Object(V8Proxy* proxy, V8ClassIndex::V8WrapperType type, void* impl); + static v8::Local<v8::Object> instantiateV8Object(V8Proxy* proxy, WrapperTypeInfo*, void* impl); static v8::Handle<v8::Object> getWrapper(Node*); }; diff --git a/WebCore/bindings/v8/V8GCController.cpp b/WebCore/bindings/v8/V8GCController.cpp index b478636..61b2a88 100644 --- a/WebCore/bindings/v8/V8GCController.cpp +++ b/WebCore/bindings/v8/V8GCController.cpp @@ -31,11 +31,18 @@ #include "config.h" #include "V8GCController.h" +#include "ActiveDOMObject.h" +#include "Attr.h" #include "DOMDataStore.h" -#include "DOMObjectsInclude.h" +#include "Frame.h" +#include "HTMLImageElement.h" +#include "HTMLNames.h" +#include "MessagePort.h" +#include "SVGElement.h" #include "V8DOMMap.h" -#include "V8Index.h" +#include "V8MessagePort.h" #include "V8Proxy.h" +#include "WrapperTypeInfo.h" #include <algorithm> #include <utility> @@ -112,7 +119,7 @@ static void enumerateDOMObjectMap(DOMObjectMap& wrapperMap) { for (DOMObjectMap::iterator it = wrapperMap.begin(), end = wrapperMap.end(); it != end; ++it) { v8::Persistent<v8::Object> wrapper(it->second); - V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(wrapper); + WrapperTypeInfo* type = V8DOMWrapper::domWrapperType(wrapper); void* object = it->first; UNUSED_PARAM(type); UNUSED_PARAM(object); @@ -123,7 +130,7 @@ class DOMObjectVisitor : public DOMWrapperMap<void>::Visitor { public: void visitDOMWrapper(void* object, v8::Persistent<v8::Object> wrapper) { - V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(wrapper); + WrapperTypeInfo* type = V8DOMWrapper::domWrapperType(wrapper); UNUSED_PARAM(type); UNUSED_PARAM(object); } @@ -181,36 +188,26 @@ class GCPrologueVisitor : public DOMWrapperMap<void>::Visitor { public: void visitDOMWrapper(void* object, v8::Persistent<v8::Object> wrapper) { - ASSERT(wrapper.IsWeak()); - V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(wrapper); - switch (type) { -#define MAKE_CASE(TYPE, NAME) \ - case V8ClassIndex::TYPE: { \ - NAME* impl = static_cast<NAME*>(object); \ - if (impl->hasPendingActivity()) \ - wrapper.ClearWeak(); \ - break; \ - } - ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE) - default: - ASSERT_NOT_REACHED(); -#undef MAKE_CASE + WrapperTypeInfo* typeInfo = V8DOMWrapper::domWrapperType(wrapper); + + // Additional handling of message port ensuring that entangled ports also + // have their wrappers entangled. This should ideally be handled when the + // ports are actually entangled in MessagePort::entangle, but to avoid + // forking MessagePort.* this is postponed to GC time. Having this postponed + // has the drawback that the wrappers are "entangled/unentangled" for each + // GC even though their entaglement most likely is still the same. + if (V8MessagePort::info.equals(typeInfo)) { + // Mark each port as in-use if it's entangled. For simplicity's sake, we assume all ports are remotely entangled, + // since the Chromium port implementation can't tell the difference. + MessagePort* port1 = static_cast<MessagePort*>(object); + if (port1->isEntangled() || port1->hasPendingActivity()) + wrapper.ClearWeak(); + } else { + ActiveDOMObject* activeDOMObject = typeInfo->toActiveDOMObject(wrapper); + if (activeDOMObject && activeDOMObject->hasPendingActivity()) + wrapper.ClearWeak(); } - - // Additional handling of message port ensuring that entangled ports also - // have their wrappers entangled. This should ideally be handled when the - // ports are actually entangled in MessagePort::entangle, but to avoid - // forking MessagePort.* this is postponed to GC time. Having this postponed - // has the drawback that the wrappers are "entangled/unentangled" for each - // GC even though their entaglement most likely is still the same. - if (type == V8ClassIndex::MESSAGEPORT) { - // Mark each port as in-use if it's entangled. For simplicity's sake, we assume all ports are remotely entangled, - // since the Chromium port implementation can't tell the difference. - MessagePort* port1 = static_cast<MessagePort*>(object); - if (port1->isEntangled()) - wrapper.ClearWeak(); } -} }; class GrouperItem { @@ -369,30 +366,20 @@ class GCEpilogueVisitor : public DOMWrapperMap<void>::Visitor { public: void visitDOMWrapper(void* object, v8::Persistent<v8::Object> wrapper) { - V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(wrapper); - switch (type) { -#define MAKE_CASE(TYPE, NAME) \ - case V8ClassIndex::TYPE: { \ - NAME* impl = static_cast<NAME*>(object); \ - if (impl->hasPendingActivity()) { \ - ASSERT(!wrapper.IsWeak()); \ - wrapper.MakeWeak(impl, &DOMDataStore::weakActiveDOMObjectCallback); \ - } \ - break; \ - } -ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE) - default: - ASSERT_NOT_REACHED(); -#undef MAKE_CASE - } - - if (type == V8ClassIndex::MESSAGEPORT) { + WrapperTypeInfo* typeInfo = V8DOMWrapper::domWrapperType(wrapper); + if (V8MessagePort::info.equals(typeInfo)) { MessagePort* port1 = static_cast<MessagePort*>(object); // We marked this port as reachable in GCPrologueVisitor. Undo this now since the // port could be not reachable in the future if it gets disentangled (and also // GCPrologueVisitor expects to see all handles marked as weak). - if (!wrapper.IsWeak() && !wrapper.IsNearDeath()) + if ((!wrapper.IsWeak() && !wrapper.IsNearDeath()) || port1->hasPendingActivity()) wrapper.MakeWeak(port1, &DOMDataStore::weakActiveDOMObjectCallback); + } else { + ActiveDOMObject* activeDOMObject = typeInfo->toActiveDOMObject(wrapper); + if (activeDOMObject && activeDOMObject->hasPendingActivity()) { + ASSERT(!wrapper.IsWeak()); + wrapper.MakeWeak(activeDOMObject, &DOMDataStore::weakActiveDOMObjectCallback); + } } } }; diff --git a/WebCore/bindings/v8/V8GCForContextDispose.cpp b/WebCore/bindings/v8/V8GCForContextDispose.cpp new file mode 100644 index 0000000..06a0555 --- /dev/null +++ b/WebCore/bindings/v8/V8GCForContextDispose.cpp @@ -0,0 +1,72 @@ +/* + * 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 "V8GCForContextDispose.h" + +#include <wtf/StdLibExtras.h> + +namespace WebCore { + +V8GCForContextDispose::V8GCForContextDispose() + : m_pseudoIdleTimer(this, &V8GCForContextDispose::pseudoIdleTimerFired) +{ +} + +void V8GCForContextDispose::notifyContextDisposed() +{ + v8::V8::ContextDisposedNotification(); + if (!m_pseudoIdleTimer.isActive()) + m_pseudoIdleTimer.startOneShot(0.8); +} + +void V8GCForContextDispose::notifyIdleSooner(double maximumFireInterval) +{ + if (m_pseudoIdleTimer.isActive()) { + double nextFireInterval = m_pseudoIdleTimer.nextFireInterval(); + if (nextFireInterval > maximumFireInterval) { + m_pseudoIdleTimer.stop(); + m_pseudoIdleTimer.startOneShot(maximumFireInterval); + } + } +} + +V8GCForContextDispose& V8GCForContextDispose::instance() +{ + DEFINE_STATIC_LOCAL(V8GCForContextDispose, staticInstance, ()); + return staticInstance; +} + +void V8GCForContextDispose::pseudoIdleTimerFired(Timer<V8GCForContextDispose>*) +{ + v8::V8::IdleNotification(); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/V8GCForContextDispose.h b/WebCore/bindings/v8/V8GCForContextDispose.h new file mode 100644 index 0000000..b15c5af --- /dev/null +++ b/WebCore/bindings/v8/V8GCForContextDispose.h @@ -0,0 +1,55 @@ +/* + * 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 V8GCForContextDispose_h +#define V8GCForContextDispose_h + +#include "Timer.h" +#include <v8.h> + +namespace WebCore { + +class V8GCForContextDispose { +public: + void notifyContextDisposed(); + void notifyIdleSooner(double maximumFireInterval); + + static V8GCForContextDispose& instance(); + +private: + V8GCForContextDispose(); // Use instance() instead. + void pseudoIdleTimerFired(Timer<V8GCForContextDispose>*); + + Timer<V8GCForContextDispose> m_pseudoIdleTimer; +}; + +} + +#endif // V8GCForContextDispose_h diff --git a/WebCore/bindings/v8/V8Helpers.cpp b/WebCore/bindings/v8/V8Helpers.cpp index a690017..486bc48 100644 --- a/WebCore/bindings/v8/V8Helpers.cpp +++ b/WebCore/bindings/v8/V8Helpers.cpp @@ -33,16 +33,10 @@ #include "DOMWindow.h" #include "NPV8Object.h" -#include "V8Index.h" #include "V8Proxy.h" namespace WebCore { -void wrapNPObject(v8::Handle<v8::Object> object, NPObject* npObject) -{ - V8DOMWrapper::setDOMWrapper(object, V8ClassIndex::NPOBJECT, npObject); -} - v8::Local<v8::Context> toV8Context(NPP npp, NPObject* npObject) { V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject); diff --git a/WebCore/bindings/v8/V8Helpers.h b/WebCore/bindings/v8/V8Helpers.h index 469833e..e90f5d6 100644 --- a/WebCore/bindings/v8/V8Helpers.h +++ b/WebCore/bindings/v8/V8Helpers.h @@ -37,9 +37,6 @@ namespace WebCore { class V8Proxy; - // Associates an NPObject with a V8 object. - void wrapNPObject(v8::Handle<v8::Object>, NPObject*); - v8::Local<v8::Context> toV8Context(NPP, NPObject*); V8Proxy* toV8Proxy(NPObject*); diff --git a/WebCore/bindings/v8/V8IsolatedContext.h b/WebCore/bindings/v8/V8IsolatedContext.h index 70ca270..5cd9c65 100644 --- a/WebCore/bindings/v8/V8IsolatedContext.h +++ b/WebCore/bindings/v8/V8IsolatedContext.h @@ -34,7 +34,6 @@ #include "IsolatedWorld.h" #include "ScriptSourceCode.h" // for WebCore::ScriptSourceCode #include "V8DOMWindow.h" -#include "V8Index.h" #include "V8Proxy.h" #include "V8Utilities.h" #include <v8.h> diff --git a/WebCore/bindings/v8/V8LazyEventListener.h b/WebCore/bindings/v8/V8LazyEventListener.h index 078dcf1..f174d23 100644 --- a/WebCore/bindings/v8/V8LazyEventListener.h +++ b/WebCore/bindings/v8/V8LazyEventListener.h @@ -60,6 +60,12 @@ namespace WebCore { virtual v8::Local<v8::Value> callListenerFunction(ScriptExecutionContext*, v8::Handle<v8::Value> jsEvent, Event*); + // Needs to return true for all event handlers implemented in JavaScript so that + // the SVG code does not add the event handler in both + // SVGUseElement::buildShadowTree and again in + // SVGUseElement::transferEventListenersToShadowTree + virtual bool wasCreatedFromMarkup() const { return true; } + String m_functionName; bool m_isSVGEvent; String m_code; diff --git a/WebCore/bindings/v8/V8NPObject.cpp b/WebCore/bindings/v8/V8NPObject.cpp index b873d5f..1ea6487 100644 --- a/WebCore/bindings/v8/V8NPObject.cpp +++ b/WebCore/bindings/v8/V8NPObject.cpp @@ -375,7 +375,7 @@ v8::Local<v8::Object> createV8ObjectForNPObject(NPObject* object, NPObject* root if (value.IsEmpty()) return value; - wrapNPObject(value, object); + V8DOMWrapper::setDOMWrapper(value, npObjectTypeInfo(), object); // KJS retains the object as part of its wrapper (see Bindings::CInstance). _NPN_RetainObject(object); @@ -394,7 +394,7 @@ void forgetV8ObjectForNPObject(NPObject* object) if (staticNPObjectMap.contains(object)) { v8::HandleScope scope; v8::Persistent<v8::Object> handle(staticNPObjectMap.get(object)); - V8DOMWrapper::setDOMWrapper(handle, WebCore::V8ClassIndex::NPOBJECT, 0); + V8DOMWrapper::setDOMWrapper(handle, npObjectTypeInfo(), 0); staticNPObjectMap.forget(object); _NPN_ReleaseObject(object); } diff --git a/WebCore/bindings/v8/V8NodeFilterCondition.cpp b/WebCore/bindings/v8/V8NodeFilterCondition.cpp index a8868b5..2170698 100644 --- a/WebCore/bindings/v8/V8NodeFilterCondition.cpp +++ b/WebCore/bindings/v8/V8NodeFilterCondition.cpp @@ -72,10 +72,7 @@ short V8NodeFilterCondition::acceptNode(ScriptState* state, Node* node) const OwnArrayPtr<v8::Handle<v8::Value> > args(new v8::Handle<v8::Value>[1]); args[0] = toV8(node); - V8Proxy* proxy = V8Proxy::retrieve(); - ASSERT(proxy); - - v8::Handle<v8::Value> result = proxy->callFunction(callback, object, 1, args.get()); + v8::Handle<v8::Value> result = V8Proxy::callFunctionWithoutFrame(callback, object, 1, args.get()); if (exceptionCatcher.HasCaught()) { state->setException(exceptionCatcher.Exception()); diff --git a/WebCore/bindings/v8/V8Proxy.cpp b/WebCore/bindings/v8/V8Proxy.cpp index 85db554..878b86a 100644 --- a/WebCore/bindings/v8/V8Proxy.cpp +++ b/WebCore/bindings/v8/V8Proxy.cpp @@ -33,14 +33,16 @@ #include "CSSMutableStyleDeclaration.h" #include "DateExtension.h" -#include "DOMObjectsInclude.h" #include "DocumentLoader.h" +#include "Frame.h" #include "FrameLoaderClient.h" #include "InspectorTimelineAgent.h" #include "Page.h" #include "PageGroup.h" #include "PlatformBridge.h" +#include "SVGElement.h" #include "ScriptController.h" +#include "Settings.h" #include "StorageNamespace.h" #include "V8Binding.h" #include "V8BindingState.h" @@ -51,19 +53,21 @@ #include "V8DOMWindow.h" #include "V8EventException.h" #include "V8HiddenPropertyName.h" -#include "V8Index.h" #include "V8IsolatedContext.h" #include "V8RangeException.h" -#include "V8SVGException.h" #include "V8XMLHttpRequestException.h" #include "V8XPathException.h" +#include "WorkerContext.h" #include "WorkerContextExecutionProxy.h" +#if ENABLE(SVG) +#include "V8SVGException.h" +#endif + #include <algorithm> #include <stdio.h> #include <utility> #include <v8.h> -#include <v8-debug.h> #include <wtf/Assertions.h> #include <wtf/OwnArrayPtr.h> #include <wtf/StdLibExtras.h> @@ -80,8 +84,6 @@ namespace WebCore { -v8::Persistent<v8::Context> V8Proxy::m_utilityContext; - // Static list of registered extensions V8Extensions V8Proxy::m_extensions; @@ -501,9 +503,32 @@ v8::Local<v8::Value> V8Proxy::callFunction(v8::Handle<v8::Function> function, v8 // execution finishs before firing the timer. m_frame->keepAlive(); +#if ENABLE(INSPECTOR) + Page* inspectedPage = InspectorTimelineAgent::instanceCount() ? m_frame->page(): 0; + if (inspectedPage) + if (InspectorTimelineAgent* timelineAgent = inspectedPage->inspectorTimelineAgent()) { + v8::ScriptOrigin origin = function->GetScriptOrigin(); + String resourceName("undefined"); + int lineNumber = 1; + if (!origin.ResourceName().IsEmpty()) { + resourceName = toWebCoreString(origin.ResourceName()); + lineNumber = function->GetScriptLineNumber() + 1; + } + timelineAgent->willCallFunction(resourceName, lineNumber); + } else + inspectedPage = 0; +#endif // !ENABLE(INSPECTOR) + m_recursion++; result = function->Call(receiver, argc, args); m_recursion--; + +#if ENABLE(INSPECTOR) + if (inspectedPage) + if (InspectorTimelineAgent* timelineAgent = inspectedPage->inspectorTimelineAgent()) + timelineAgent->didCallFunction(); +#endif // !ENABLE(INSPECTOR) + } // Release the storage mutex if applicable. @@ -518,6 +543,17 @@ v8::Local<v8::Value> V8Proxy::callFunction(v8::Handle<v8::Function> function, v8 return result; } +v8::Local<v8::Value> V8Proxy::callFunctionWithoutFrame(v8::Handle<v8::Function> function, v8::Handle<v8::Object> receiver, int argc, v8::Handle<v8::Value> args[]) +{ + V8GCController::checkMemoryUsage(); + v8::Local<v8::Value> result = function->Call(receiver, argc, args); + + if (v8::V8::IsDead()) + handleFatalErrorInV8(); + + return result; +} + v8::Local<v8::Value> V8Proxy::newInstance(v8::Handle<v8::Function> constructor, int argc, v8::Handle<v8::Value> args[]) { // No artificial limitations on the depth of recursion, see comment in @@ -594,7 +630,7 @@ V8Proxy* V8Proxy::retrieve(Frame* frame) { if (!frame) return 0; - return frame->script()->canExecuteScripts() ? frame->script()->proxy() : 0; + return frame->script()->canExecuteScripts(NotAboutToExecuteScript) ? frame->script()->proxy() : 0; } V8Proxy* V8Proxy::retrieve(ScriptExecutionContext* context) @@ -675,10 +711,12 @@ void V8Proxy::setDOMException(int exceptionCode) exception = toV8(XPathException::create(description)); break; #endif + default: + ASSERT_NOT_REACHED(); } - ASSERT(!exception.IsEmpty()); - v8::ThrowException(exception); + if (!exception.IsEmpty()) + v8::ThrowException(exception); } v8::Handle<v8::Value> V8Proxy::throwError(ErrorType type, const char* message) @@ -754,95 +792,11 @@ v8::Handle<v8::Value> V8Proxy::checkNewLegal(const v8::Arguments& args) return args.This(); } -void V8Proxy::bindJsObjectToWindow(Frame* frame, const char* name, int type, v8::Handle<v8::FunctionTemplate> descriptor, void* impl) -{ - // Get environment. - v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(frame); - if (v8Context.IsEmpty()) - return; // JS not enabled. - - v8::Context::Scope scope(v8Context); - v8::Handle<v8::Object> instance = descriptor->GetFunction(); - V8DOMWrapper::setDOMWrapper(instance, type, impl); - - v8::Handle<v8::Object> global = v8Context->Global(); - global->Set(v8::String::New(name), instance); -} - void V8Proxy::processConsoleMessages() { V8ConsoleMessage::processDelayed(); } -// Create the utility context for holding JavaScript functions used internally -// which are not visible to JavaScript executing on the page. -void V8Proxy::createUtilityContext() -{ - ASSERT(m_utilityContext.IsEmpty()); - - v8::HandleScope scope; - v8::Handle<v8::ObjectTemplate> globalTemplate = v8::ObjectTemplate::New(); - m_utilityContext = v8::Context::New(0, globalTemplate); - v8::Context::Scope contextScope(m_utilityContext); - - // Compile JavaScript function for retrieving the source line of the top - // JavaScript stack frame. - DEFINE_STATIC_LOCAL(const char*, frameSourceLineSource, - ("function frameSourceLine(exec_state) {" - " return exec_state.frame(0).sourceLine();" - "}")); - v8::Script::Compile(v8::String::New(frameSourceLineSource))->Run(); - - // Compile JavaScript function for retrieving the source name of the top - // JavaScript stack frame. - DEFINE_STATIC_LOCAL(const char*, frameSourceNameSource, - ("function frameSourceName(exec_state) {" - " var frame = exec_state.frame(0);" - " if (frame.func().resolved() && " - " frame.func().script() && " - " frame.func().script().name()) {" - " return frame.func().script().name();" - " }" - "}")); - v8::Script::Compile(v8::String::New(frameSourceNameSource))->Run(); -} - -bool V8Proxy::sourceLineNumber(int& result) -{ - v8::HandleScope scope; - v8::Handle<v8::Context> v8UtilityContext = V8Proxy::utilityContext(); - if (v8UtilityContext.IsEmpty()) - return false; - v8::Context::Scope contextScope(v8UtilityContext); - v8::Handle<v8::Function> frameSourceLine; - frameSourceLine = v8::Local<v8::Function>::Cast(v8UtilityContext->Global()->Get(v8::String::New("frameSourceLine"))); - if (frameSourceLine.IsEmpty()) - return false; - v8::Handle<v8::Value> value = v8::Debug::Call(frameSourceLine); - if (value.IsEmpty()) - return false; - result = value->Int32Value(); - return true; -} - -bool V8Proxy::sourceName(String& result) -{ - v8::HandleScope scope; - v8::Handle<v8::Context> v8UtilityContext = utilityContext(); - if (v8UtilityContext.IsEmpty()) - return false; - v8::Context::Scope contextScope(v8UtilityContext); - v8::Handle<v8::Function> frameSourceName; - frameSourceName = v8::Local<v8::Function>::Cast(v8UtilityContext->Global()->Get(v8::String::New("frameSourceName"))); - if (frameSourceName.IsEmpty()) - return false; - v8::Handle<v8::Value> value = v8::Debug::Call(frameSourceName); - if (value.IsEmpty()) - return false; - result = toWebCoreString(value); - return true; -} - void V8Proxy::registerExtensionWithV8(v8::Extension* extension) { // If the extension exists in our list, it was already registered with V8. diff --git a/WebCore/bindings/v8/V8Proxy.h b/WebCore/bindings/v8/V8Proxy.h index 44ed506..98bc902 100644 --- a/WebCore/bindings/v8/V8Proxy.h +++ b/WebCore/bindings/v8/V8Proxy.h @@ -39,7 +39,7 @@ #include "V8DOMWindowShell.h" #include "V8DOMWrapper.h" #include "V8GCController.h" -#include "V8Index.h" +#include "WrapperTypeInfo.h" #include <v8.h> #include <wtf/PassRefPtr.h> // so generated bindings don't have to #include <wtf/Vector.h> @@ -76,7 +76,7 @@ namespace WebCore { const char* const name; v8::AccessorGetter getter; v8::AccessorSetter setter; - V8ClassIndex::V8WrapperType data; + WrapperTypeInfo* data; v8::AccessControl settings; v8::PropertyAttribute attribute; bool onProto; @@ -89,7 +89,7 @@ namespace WebCore { (attribute.onProto ? proto : instance)->SetAccessor(v8::String::New(attribute.name), attribute.getter, attribute.setter, - attribute.data == V8ClassIndex::INVALID_CLASS_INDEX ? v8::Handle<v8::Value>() : v8::Integer::New(V8ClassIndex::ToInt(attribute.data)), + v8::External::Wrap(attribute.data), attribute.settings, attribute.attribute); } @@ -224,6 +224,9 @@ namespace WebCore { // Call the function with the given receiver and arguments. v8::Local<v8::Value> callFunction(v8::Handle<v8::Function>, v8::Handle<v8::Object>, int argc, v8::Handle<v8::Value> argv[]); + // Call the function with the given receiver and arguments. + static v8::Local<v8::Value> callFunctionWithoutFrame(v8::Handle<v8::Function>, v8::Handle<v8::Object>, int argc, v8::Handle<v8::Value> argv[]); + // Call the function as constructor with the given arguments. v8::Local<v8::Value> newInstance(v8::Handle<v8::Function>, int argc, v8::Handle<v8::Value> argv[]); @@ -298,26 +301,12 @@ namespace WebCore { // Schedule an error object to be thrown. static v8::Handle<v8::Value> throwError(ErrorType, const char* message); - // Create an instance of a function descriptor and set to the global object - // as a named property. Used by v8_test_shell. - static void bindJsObjectToWindow(Frame*, const char* name, int type, v8::Handle<v8::FunctionTemplate>, void*); - - template <int tag, typename T> - static v8::Handle<v8::Value> constructDOMObject(const v8::Arguments&); + template <typename T> + static v8::Handle<v8::Value> constructDOMObject(const v8::Arguments&, WrapperTypeInfo*); // Process any pending JavaScript console messages. static void processConsoleMessages(); - // Function for retrieving the line number and source name for the top - // JavaScript stack frame. - // - // It will return true if the line number was successfully retrieved and written - // into the |result| parameter, otherwise the function will return false. It may - // fail due to a stck overflow in the underlying JavaScript implentation, handling - // of such exception is up to the caller. - static bool sourceLineNumber(int& result); - static bool sourceName(String& result); - v8::Local<v8::Context> context(); v8::Local<v8::Context> mainWorldContext(); @@ -368,23 +357,10 @@ namespace WebCore { static const char* svgExceptionName(int exceptionCode); #endif - static void createUtilityContext(); - - // Returns a local handle of the utility context. - static v8::Local<v8::Context> utilityContext() - { - if (m_utilityContext.IsEmpty()) - createUtilityContext(); - return v8::Local<v8::Context>::New(m_utilityContext); - } - Frame* m_frame; // For the moment, we have one of these. Soon we will have one per DOMWrapperWorld. RefPtr<V8DOMWindowShell> m_windowShell; - - // Utility context holding JavaScript functions used internally. - static v8::Persistent<v8::Context> m_utilityContext; int m_handlerLineNumber; @@ -418,8 +394,8 @@ namespace WebCore { IsolatedWorldMap m_isolatedWorlds; }; - template <int tag, typename T> - v8::Handle<v8::Value> V8Proxy::constructDOMObject(const v8::Arguments& args) + template <typename T> + v8::Handle<v8::Value> V8Proxy::constructDOMObject(const v8::Arguments& args, WrapperTypeInfo* type) { if (!args.IsConstructCall()) return throwError(V8Proxy::TypeError, "DOM object constructor cannot be called as a function."); @@ -427,7 +403,7 @@ namespace WebCore { // Note: it's OK to let this RefPtr go out of scope because we also call // SetDOMWrapper(), which effectively holds a reference to obj. RefPtr<T> obj = T::create(); - V8DOMWrapper::setDOMWrapper(args.Holder(), tag, obj.get()); + V8DOMWrapper::setDOMWrapper(args.Holder(), type, obj.get()); obj->ref(); V8DOMWrapper::setJSWrapperForDOMObject(obj.get(), v8::Persistent<v8::Object>::New(args.Holder())); return args.Holder(); @@ -449,19 +425,22 @@ namespace WebCore { } inline v8::Handle<v8::Primitive> throwError(const char* message, V8Proxy::ErrorType type = V8Proxy::TypeError) { - V8Proxy::throwError(type, message); + if (!v8::V8::IsExecutionTerminating()) + V8Proxy::throwError(type, message); return v8::Undefined(); } inline v8::Handle<v8::Primitive> throwError(ExceptionCode ec) { - V8Proxy::setDOMException(ec); + if (!v8::V8::IsExecutionTerminating()) + V8Proxy::setDOMException(ec); return v8::Undefined(); } inline v8::Handle<v8::Primitive> throwError(v8::Local<v8::Value> exception) { - v8::ThrowException(exception); + if (!v8::V8::IsExecutionTerminating()) + v8::ThrowException(exception); return v8::Undefined(); } diff --git a/WebCore/bindings/v8/V8SVGPODTypeWrapper.h b/WebCore/bindings/v8/V8SVGPODTypeWrapper.h index d4cdcf8..c044a06 100644 --- a/WebCore/bindings/v8/V8SVGPODTypeWrapper.h +++ b/WebCore/bindings/v8/V8SVGPODTypeWrapper.h @@ -396,13 +396,13 @@ public: class V8SVGPODTypeUtil { public: template <class P> - static P toSVGPODType(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Value> object, bool& ok); + static P toSVGPODType(WrapperTypeInfo* info, v8::Handle<v8::Value> object, bool& ok); }; template <class P> -P V8SVGPODTypeUtil::toSVGPODType(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Value> object, bool& ok) +P V8SVGPODTypeUtil::toSVGPODType(WrapperTypeInfo* info, v8::Handle<v8::Value> object, bool& ok) { - if (!V8DOMWrapper::isWrapperOfType(object, type)) { + if (!V8DOMWrapper::isWrapperOfType(object, info)) { ok = false; return P(); } diff --git a/WebCore/bindings/v8/V8Utilities.cpp b/WebCore/bindings/v8/V8Utilities.cpp index c7314f1..ffccb06 100644 --- a/WebCore/bindings/v8/V8Utilities.cpp +++ b/WebCore/bindings/v8/V8Utilities.cpp @@ -125,54 +125,17 @@ void navigateIfAllowed(Frame* frame, const KURL& url, bool lockHistory, bool loc frame->redirectScheduler()->scheduleLocationChange(url.string(), callingFrame->loader()->outgoingReferrer(), lockHistory, lockBackForwardList, processingUserGesture()); } -ScriptExecutionContext* getScriptExecutionContext(ScriptState* scriptState) +ScriptExecutionContext* getScriptExecutionContext() { #if ENABLE(WORKERS) - WorkerContextExecutionProxy* proxy = WorkerContextExecutionProxy::retrieve(); - if (proxy) - return proxy->workerContext()->scriptExecutionContext(); + if (WorkerScriptController* controller = WorkerScriptController::controllerForContext()) + return controller->workerContext(); #endif - Frame* frame; - if (scriptState) { - v8::HandleScope handleScope; - frame = V8Proxy::retrieveFrame(scriptState->context()); - } else - frame = V8Proxy::retrieveFrameForCurrentContext(); - - if (frame) + if (Frame* frame = V8Proxy::retrieveFrameForCurrentContext()) return frame->document()->scriptExecutionContext(); return 0; } -void reportException(ScriptState* scriptState, v8::TryCatch& exceptionCatcher) -{ - String errorMessage; - int lineNumber = 0; - String sourceURL; - - // There can be a situation that an exception is thrown without setting a message. - v8::Local<v8::Message> message = exceptionCatcher.Message(); - if (message.IsEmpty()) { - v8::Local<v8::String> exceptionString = exceptionCatcher.Exception()->ToString(); - // Conversion of the exception object to string can fail if an - // exception is thrown during conversion. - if (!exceptionString.IsEmpty()) - errorMessage = toWebCoreString(exceptionString); - } else { - errorMessage = toWebCoreString(message->Get()); - lineNumber = message->GetLineNumber(); - sourceURL = toWebCoreString(message->GetScriptResourceName()); - } - - // Do not report the exception if the current execution context is Document because we do not want to lead to duplicate error messages in the console. - // FIXME (31171): need better design to solve the duplicate error message reporting problem. - ScriptExecutionContext* context = getScriptExecutionContext(scriptState); - // During the frame teardown, there may not be a valid context. - if (context && !context->isDocument()) - context->reportException(errorMessage, lineNumber, sourceURL); - exceptionCatcher.Reset(); -} - } // namespace WebCore diff --git a/WebCore/bindings/v8/V8Utilities.h b/WebCore/bindings/v8/V8Utilities.h index 944823a..cbe7a7b 100644 --- a/WebCore/bindings/v8/V8Utilities.h +++ b/WebCore/bindings/v8/V8Utilities.h @@ -54,12 +54,7 @@ namespace WebCore { KURL completeURL(const String& relativeURL); void navigateIfAllowed(Frame*, const KURL&, bool lockHistory, bool lockBackForwardList); - ScriptExecutionContext* getScriptExecutionContext(ScriptState*); - inline ScriptExecutionContext* getScriptExecutionContext() { - return getScriptExecutionContext(0); - } - - void reportException(ScriptState*, v8::TryCatch&); + ScriptExecutionContext* getScriptExecutionContext(); class AllowAllocation { public: diff --git a/WebCore/bindings/v8/V8WorkerContextErrorHandler.cpp b/WebCore/bindings/v8/V8WorkerContextErrorHandler.cpp new file mode 100644 index 0000000..5a75a40 --- /dev/null +++ b/WebCore/bindings/v8/V8WorkerContextErrorHandler.cpp @@ -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. + */ + +#include "config.h" + +#if ENABLE(WORKERS) + +#include "V8WorkerContextErrorHandler.h" + +#include "ErrorEvent.h" +#include "V8Binding.h" + +namespace WebCore { + +V8WorkerContextErrorHandler::V8WorkerContextErrorHandler(v8::Local<v8::Object> listener, bool isInline, const WorldContextHandle& worldContext) + : V8WorkerContextEventListener(listener, isInline, worldContext) +{ +} + +v8::Local<v8::Value> V8WorkerContextErrorHandler::callListenerFunction(ScriptExecutionContext* context, v8::Handle<v8::Value> jsEvent, Event* event) +{ + ASSERT(event->isErrorEvent()); + v8::Local<v8::Object> listener = getListenerObject(context); + v8::Local<v8::Value> returnValue; + if (!listener.IsEmpty() && listener->IsFunction()) { + ErrorEvent* errorEvent = static_cast<ErrorEvent*>(event); + v8::Local<v8::Function> callFunction = v8::Local<v8::Function>::Cast(listener); + v8::Local<v8::Object> thisValue = v8::Context::GetCurrent()->Global(); + v8::Handle<v8::Value> parameters[3] = { v8String(errorEvent->message()), v8String(errorEvent->filename()), v8::Integer::New(errorEvent->lineno()) }; + returnValue = callFunction->Call(thisValue, 3, parameters); + if (!returnValue.IsEmpty() && returnValue->IsBoolean() && !returnValue->BooleanValue()) + event->preventDefault(); + } + return returnValue; +} + +} // namespace WebCore + +#endif // WORKERS diff --git a/WebCore/bindings/v8/V8WorkerContextErrorHandler.h b/WebCore/bindings/v8/V8WorkerContextErrorHandler.h new file mode 100644 index 0000000..cd1e0e6 --- /dev/null +++ b/WebCore/bindings/v8/V8WorkerContextErrorHandler.h @@ -0,0 +1,59 @@ +/* + * 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 V8WorkerContextErrorHandler_h +#define V8WorkerContextErrorHandler_h + +#if ENABLE(WORKERS) + +#include "V8WorkerContextEventListener.h" +#include <v8.h> +#include <wtf/PassRefPtr.h> + +namespace WebCore { + +class V8WorkerContextErrorHandler : public V8WorkerContextEventListener { +public: + static PassRefPtr<V8WorkerContextErrorHandler> create(v8::Local<v8::Object> listener, bool isInline, const WorldContextHandle& worldContext) + { + return adoptRef(new V8WorkerContextErrorHandler(listener, isInline, worldContext)); + } + +private: + V8WorkerContextErrorHandler(v8::Local<v8::Object> listener, bool isInline, const WorldContextHandle& worldContext); + + virtual v8::Local<v8::Value> callListenerFunction(ScriptExecutionContext*, v8::Handle<v8::Value> jsEvent, Event*); +}; + +} // namespace WebCore + +#endif // WORKERS + +#endif // V8WorkerContextErrorHandler_h diff --git a/WebCore/bindings/v8/V8WorkerContextEventListener.cpp b/WebCore/bindings/v8/V8WorkerContextEventListener.cpp index fa89ae6..30b9865 100644 --- a/WebCore/bindings/v8/V8WorkerContextEventListener.cpp +++ b/WebCore/bindings/v8/V8WorkerContextEventListener.cpp @@ -82,56 +82,6 @@ void V8WorkerContextEventListener::handleEvent(ScriptExecutionContext* context, invokeEventHandler(context, event, jsEvent); } -bool V8WorkerContextEventListener::reportError(ScriptExecutionContext* context, const String& message, const String& url, int lineNumber) -{ - if (!context) - return false; - - // The callback function can clear the event listener and destroy 'this' object. Keep a local reference to it. - RefPtr<V8AbstractEventListener> protect(this); - - v8::HandleScope handleScope; - - WorkerContextExecutionProxy* proxy = workerProxy(context); - if (!proxy) - return false; - - v8::Handle<v8::Context> v8Context = proxy->context(); - if (v8Context.IsEmpty()) - return false; - - // Enter the V8 context in which to perform the event handling. - v8::Context::Scope scope(v8Context); - - v8::Local<v8::Object> listener = getListenerObject(context); - v8::Local<v8::Value> returnValue; - { - // Catch exceptions thrown in calling the function so they do not propagate to javascript code that caused the event to fire. - v8::TryCatch tryCatch; - tryCatch.SetVerbose(true); - - // Call the function. - if (!listener.IsEmpty() && listener->IsFunction()) { - v8::Local<v8::Function> callFunction = v8::Local<v8::Function>::Cast(listener); - v8::Local<v8::Object> thisValue = v8::Context::GetCurrent()->Global(); - - v8::Handle<v8::Value> parameters[3] = { v8String(message), v8String(url), v8::Integer::New(lineNumber) }; - returnValue = callFunction->Call(thisValue, 3, parameters); - } - - // If an error occurs while handling the script error, it should be bubbled up. - if (tryCatch.HasCaught()) { - tryCatch.Reset(); - return false; - } - } - - // If the function returns false, then the error is handled. Otherwise, the error is not handled. - bool errorHandled = returnValue->IsBoolean() && !returnValue->BooleanValue(); - - return errorHandled; -} - v8::Local<v8::Value> V8WorkerContextEventListener::callListenerFunction(ScriptExecutionContext* context, v8::Handle<v8::Value> jsEvent, Event* event) { v8::Local<v8::Function> handlerFunction = getListenerFunction(context); diff --git a/WebCore/bindings/v8/V8WorkerContextEventListener.h b/WebCore/bindings/v8/V8WorkerContextEventListener.h index 4487497..1d0bfc8 100644 --- a/WebCore/bindings/v8/V8WorkerContextEventListener.h +++ b/WebCore/bindings/v8/V8WorkerContextEventListener.h @@ -50,11 +50,11 @@ namespace WebCore { } virtual void handleEvent(ScriptExecutionContext*, Event*); - virtual bool reportError(ScriptExecutionContext*, const String& message, const String& url, int lineNumber); - private: + protected: V8WorkerContextEventListener(v8::Local<v8::Object> listener, bool isInline, const WorldContextHandle& worldContext); + private: virtual v8::Local<v8::Value> callListenerFunction(ScriptExecutionContext*, v8::Handle<v8::Value> jsEvent, Event*); v8::Local<v8::Object> getReceiverObject(ScriptExecutionContext*, Event*); }; diff --git a/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp b/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp index e4b417e..16e0b41 100644 --- a/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp +++ b/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp @@ -35,33 +35,20 @@ #include "WorkerContextExecutionProxy.h" -#include "DOMCoreException.h" #include "DedicatedWorkerContext.h" #include "Event.h" -#include "EventSource.h" -#include "Notification.h" -#include "NotificationCenter.h" -#include "EventException.h" -#include "MessagePort.h" -#include "RangeException.h" #include "SharedWorker.h" #include "SharedWorkerContext.h" #include "V8Binding.h" +#include "V8ConsoleMessage.h" #include "V8DOMMap.h" -#include "V8Index.h" +#include "V8DedicatedWorkerContext.h" #include "V8Proxy.h" -#include "V8WorkerContext.h" -#include "V8WorkerContextEventListener.h" -#if ENABLE(WEB_SOCKETS) -#include "WebSocket.h" -#endif +#include "V8SharedWorkerContext.h" #include "Worker.h" #include "WorkerContext.h" -#include "WorkerLocation.h" -#include "WorkerNavigator.h" #include "WorkerScriptController.h" -#include "XMLHttpRequest.h" -#include "XMLHttpRequestException.h" +#include "WrapperTypeInfo.h" namespace WebCore { @@ -71,6 +58,26 @@ static void reportFatalErrorInV8(const char* location, const char* message) CRASH(); } +static void v8MessageHandler(v8::Handle<v8::Message> message, v8::Handle<v8::Value> data) +{ + static bool isReportingException = false; + // Exceptions that occur in error handler should be ignored since in that case + // WorkerContext::reportException will send the exception to the worker object. + if (isReportingException) + return; + isReportingException = true; + + // During the frame teardown, there may not be a valid context. + if (ScriptExecutionContext* context = getScriptExecutionContext()) { + String errorMessage = toWebCoreString(message->Get()); + int lineNumber = message->GetLineNumber(); + String sourceURL = toWebCoreString(message->GetScriptResourceName()); + context->reportException(errorMessage, lineNumber, sourceURL); + } + + isReportingException = false; +} + WorkerContextExecutionProxy::WorkerContextExecutionProxy(WorkerContext* workerContext) : m_workerContext(workerContext) , m_recursion(0) @@ -100,21 +107,6 @@ void WorkerContextExecutionProxy::dispose() } } -WorkerContextExecutionProxy* WorkerContextExecutionProxy::retrieve() -{ - // Happens on frame destruction, check otherwise GetCurrent() will crash. - if (!v8::Context::InContext()) - return 0; - v8::Handle<v8::Context> context = v8::Context::GetCurrent(); - v8::Handle<v8::Object> global = context->Global(); - global = V8DOMWrapper::lookupDOMWrapper(V8WorkerContext::GetTemplate(), global); - // Return 0 if the current executing context is not the worker context. - if (global.IsEmpty()) - return 0; - WorkerContext* workerContext = V8WorkerContext::toNative(global); - return workerContext->script()->proxy(); -} - void WorkerContextExecutionProxy::initV8IfNeeded() { static bool v8Initialized = false; @@ -134,46 +126,53 @@ void WorkerContextExecutionProxy::initV8IfNeeded() v8Initialized = true; } -void WorkerContextExecutionProxy::initContextIfNeeded() +bool WorkerContextExecutionProxy::initContextIfNeeded() { // Bail out if the context has already been initialized. if (!m_context.IsEmpty()) - return; + return true; + + // Setup the security handlers and message listener. This only has + // to be done once. + static bool isV8Initialized = false; + if (!isV8Initialized) + v8::V8::AddMessageListener(&v8MessageHandler); // Create a new environment v8::Persistent<v8::ObjectTemplate> globalTemplate; m_context = v8::Context::New(0, globalTemplate); + if (m_context.IsEmpty()) + return false; // Starting from now, use local context only. v8::Local<v8::Context> context = v8::Local<v8::Context>::New(m_context); - v8::Context::Scope scope(context); - // Allocate strings used during initialization. - v8::Handle<v8::String> implicitProtoString = v8::String::New("__proto__"); + v8::Context::Scope scope(context); // Create a new JS object and use it as the prototype for the shadow global object. - V8ClassIndex::V8WrapperType contextType = V8ClassIndex::DEDICATEDWORKERCONTEXT; + WrapperTypeInfo* contextType = &V8DedicatedWorkerContext::info; #if ENABLE(SHARED_WORKERS) if (!m_workerContext->isDedicatedWorkerContext()) - contextType = V8ClassIndex::SHAREDWORKERCONTEXT; + contextType = &V8SharedWorkerContext::info; #endif v8::Handle<v8::Function> workerContextConstructor = V8DOMWrapper::getConstructorForContext(contextType, context); v8::Local<v8::Object> jsWorkerContext = SafeAllocation::newInstance(workerContextConstructor); // Bail out if allocation failed. if (jsWorkerContext.IsEmpty()) { dispose(); - return; + return false; } // Wrap the object. - V8DOMWrapper::setDOMWrapper(jsWorkerContext, V8ClassIndex::ToInt(contextType), m_workerContext); + V8DOMWrapper::setDOMWrapper(jsWorkerContext, contextType, m_workerContext); V8DOMWrapper::setJSWrapperForDOMObject(m_workerContext, v8::Persistent<v8::Object>::New(jsWorkerContext)); m_workerContext->ref(); // Insert the object instance as the prototype of the shadow object. - v8::Handle<v8::Object> globalObject = m_context->Global(); - globalObject->Set(implicitProtoString, jsWorkerContext); + v8::Handle<v8::Object> globalObject = v8::Handle<v8::Object>::Cast(m_context->Global()->GetPrototype()); + globalObject->SetPrototype(jsWorkerContext); + return true; } bool WorkerContextExecutionProxy::forgetV8EventObject(Event* event) @@ -189,7 +188,9 @@ ScriptValue WorkerContextExecutionProxy::evaluate(const String& script, const St { v8::HandleScope hs; - initContextIfNeeded(); + if (!initContextIfNeeded()) + return ScriptValue(); + v8::Context::Scope scope(m_context); v8::TryCatch exceptionCatcher; @@ -198,6 +199,9 @@ ScriptValue WorkerContextExecutionProxy::evaluate(const String& script, const St v8::Handle<v8::Script> compiledScript = V8Proxy::compileScript(scriptString, fileName, baseLine); v8::Local<v8::Value> result = runScript(compiledScript); + if (!exceptionCatcher.CanContinue()) + return ScriptValue(); + if (exceptionCatcher.HasCaught()) { v8::Local<v8::Message> message = exceptionCatcher.Message(); state->hadException = true; @@ -247,11 +251,6 @@ v8::Local<v8::Value> WorkerContextExecutionProxy::runScript(v8::Handle<v8::Scrip return result; } -PassRefPtr<V8EventListener> WorkerContextExecutionProxy::findOrCreateEventListener(v8::Local<v8::Value> object, bool isInline, bool findOnly) -{ - return findOnly ? V8EventListenerList::findWrapper(object, isInline) : V8EventListenerList::findOrCreateWrapper<V8WorkerContextEventListener>(object, isInline); -} - void WorkerContextExecutionProxy::trackEvent(Event* event) { m_events.append(event); diff --git a/WebCore/bindings/v8/WorkerContextExecutionProxy.h b/WebCore/bindings/v8/WorkerContextExecutionProxy.h index 67a472b..58824b9 100644 --- a/WebCore/bindings/v8/WorkerContextExecutionProxy.h +++ b/WebCore/bindings/v8/WorkerContextExecutionProxy.h @@ -35,8 +35,6 @@ #if ENABLE(WORKERS) #include "ScriptValue.h" -#include "V8EventListenerList.h" -#include "V8Index.h" #include <v8.h> #include <wtf/OwnPtr.h> #include <wtf/Vector.h> @@ -45,8 +43,6 @@ namespace WebCore { class Event; class EventTarget; - class V8EventListener; - class V8WorkerContextEventListener; class WorkerContext; struct WorkerContextExecutionState { @@ -64,9 +60,6 @@ namespace WebCore { WorkerContextExecutionProxy(WorkerContext*); ~WorkerContextExecutionProxy(); - // Finds/creates event listener wrappers. - PassRefPtr<V8EventListener> findOrCreateEventListener(v8::Local<v8::Value> listener, bool isInline, bool findOnly); - // Track the event so that we can detach it from the JS wrapper when a worker // terminates. This is needed because we need to be able to dispose these // events and releases references to their event targets: WorkerContext. @@ -78,15 +71,9 @@ namespace WebCore { // Returns a local handle of the context. v8::Local<v8::Context> context() { return v8::Local<v8::Context>::New(m_context); } - // Returns WorkerContext object. - WorkerContext* workerContext() { return m_workerContext; } - - // Returns WorkerContextExecutionProxy object of the currently executing context. 0 will be returned if the current executing context is not the worker context. - static WorkerContextExecutionProxy* retrieve(); - private: void initV8IfNeeded(); - void initContextIfNeeded(); + bool initContextIfNeeded(); void dispose(); // Run an already compiled script. diff --git a/WebCore/bindings/v8/WorkerScriptController.cpp b/WebCore/bindings/v8/WorkerScriptController.cpp index f2311bf..7db0d8d 100644 --- a/WebCore/bindings/v8/WorkerScriptController.cpp +++ b/WebCore/bindings/v8/WorkerScriptController.cpp @@ -41,6 +41,7 @@ #include "DOMTimer.h" #include "V8DOMMap.h" #include "V8Proxy.h" +#include "V8WorkerContext.h" #include "WorkerContext.h" #include "WorkerContextExecutionProxy.h" #include "WorkerObjectProxy.h" @@ -85,11 +86,13 @@ ScriptValue WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, return result; } -void WorkerScriptController::forbidExecution() +void WorkerScriptController::forbidExecution(ForbidExecutionOption option) { - // This function is called from another thread. + // This function may be called from another thread. MutexLocker lock(m_sharedDataMutex); m_executionForbidden = true; + if (option == TerminateRunningScript) + v8::V8::TerminateExecution(); } void WorkerScriptController::setException(ScriptValue exception) @@ -97,6 +100,21 @@ void WorkerScriptController::setException(ScriptValue exception) throwError(*exception.v8Value()); } +WorkerScriptController* WorkerScriptController::controllerForContext() +{ + // Happens on frame destruction, check otherwise GetCurrent() will crash. + if (!v8::Context::InContext()) + return 0; + v8::Handle<v8::Context> context = v8::Context::GetCurrent(); + v8::Handle<v8::Object> global = context->Global(); + global = V8DOMWrapper::lookupDOMWrapper(V8WorkerContext::GetTemplate(), global); + // Return 0 if the current executing context is not the worker context. + if (global.IsEmpty()) + return 0; + WorkerContext* workerContext = V8WorkerContext::toNative(global); + return workerContext->script(); +} + } // namespace WebCore #endif // ENABLE(WORKERS) diff --git a/WebCore/bindings/v8/WorkerScriptController.h b/WebCore/bindings/v8/WorkerScriptController.h index 07e224c..616697a 100644 --- a/WebCore/bindings/v8/WorkerScriptController.h +++ b/WebCore/bindings/v8/WorkerScriptController.h @@ -48,14 +48,19 @@ namespace WebCore { WorkerScriptController(WorkerContext*); ~WorkerScriptController(); - WorkerContextExecutionProxy* proxy() { return m_proxy.get(); } + WorkerContextExecutionProxy* proxy() { return m_executionForbidden ? 0 : m_proxy.get(); } + WorkerContext* workerContext() { return m_workerContext; } ScriptValue evaluate(const ScriptSourceCode&); ScriptValue evaluate(const ScriptSourceCode&, ScriptValue* exception); void setException(ScriptValue); - void forbidExecution(); + enum ForbidExecutionOption { TerminateRunningScript, LetRunningScriptFinish }; + void forbidExecution(ForbidExecutionOption); + + // Returns WorkerScriptController for the currently executing context. 0 will be returned if the current executing context is not the worker context. + static WorkerScriptController* controllerForContext(); private: WorkerContext* m_workerContext; diff --git a/WebCore/bindings/v8/WrapperTypeInfo.h b/WebCore/bindings/v8/WrapperTypeInfo.h new file mode 100644 index 0000000..1d1cbfd --- /dev/null +++ b/WebCore/bindings/v8/WrapperTypeInfo.h @@ -0,0 +1,86 @@ +/* + * 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 WrapperTypeInfo_h +#define WrapperTypeInfo_h + +#include <v8.h> + +namespace WebCore { + + class ActiveDOMObject; + + static const int v8DOMWrapperTypeIndex = 0; + static const int v8DOMWrapperObjectIndex = 1; + static const int v8DOMHiddenReferenceArrayIndex = 2; + static const int v8DefaultWrapperInternalFieldCount = 3; + + typedef v8::Persistent<v8::FunctionTemplate> (*GetTemplateFunction)(); + typedef void (*DerefObjectFunction)(void*); + typedef ActiveDOMObject* (*ToActiveDOMObjectFunction)(v8::Handle<v8::Object>); + + // This struct provides a way to store a bunch of information that is helpful when unwrapping + // v8 objects. Each v8 bindings class has exactly one static WrapperTypeInfo member, so + // comparing pointers is a safe way to determine if types match. + struct WrapperTypeInfo { + + static WrapperTypeInfo* unwrap(v8::Handle<v8::Value> typeInfoWrapper) + { + return reinterpret_cast<WrapperTypeInfo*>(v8::External::Unwrap(typeInfoWrapper)); + } + + + bool equals(const WrapperTypeInfo* that) const + { + return this == that; + } + + v8::Persistent<v8::FunctionTemplate> getTemplate() { return getTemplateFunction(); } + + void derefObject(void* object) + { + if (derefObjectFunction) + derefObjectFunction(object); + } + + ActiveDOMObject* toActiveDOMObject(v8::Handle<v8::Object> object) + { + if (!toActiveDOMObjectFunction) + return 0; + return toActiveDOMObjectFunction(object); + } + + const GetTemplateFunction getTemplateFunction; + const DerefObjectFunction derefObjectFunction; + const ToActiveDOMObjectFunction toActiveDOMObjectFunction; + }; +} + +#endif // WrapperTypeInfo_h diff --git a/WebCore/bindings/v8/custom/V8AbstractWorkerCustom.cpp b/WebCore/bindings/v8/custom/V8AbstractWorkerCustom.cpp deleted file mode 100644 index e776438..0000000 --- a/WebCore/bindings/v8/custom/V8AbstractWorkerCustom.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2009 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 "V8AbstractWorker.h" - -#include "AbstractWorker.h" -#include "ExceptionCode.h" -#include "ScriptExecutionContext.h" -#include "V8Binding.h" -#include "V8Proxy.h" -#include "V8Utilities.h" -#include "WorkerContextExecutionProxy.h" - -namespace WebCore { - -v8::Handle<v8::Value> V8AbstractWorker::addEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS(L"DOM.AbstractWorker.addEventListener()"); - AbstractWorker* worker = V8AbstractWorker::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(worker, args[1], false, ListenerFindOrCreate); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - worker->addEventListener(type, listener, useCapture); - - createHiddenDependency(args.Holder(), args[1], cacheIndex); - } - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8AbstractWorker::removeEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS(L"DOM.AbstractWorker.removeEventListener()"); - AbstractWorker* worker = V8AbstractWorker::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(worker, args[1], false, ListenerFindOnly); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - worker->removeEventListener(type, listener.get(), useCapture); - - removeHiddenDependency(args.Holder(), args[1], cacheIndex); - } - - return v8::Undefined(); -} - -} // namespace WebCore - -#endif // ENABLE(WORKERS) diff --git a/WebCore/bindings/v8/custom/V8CSSStyleSheetCustom.cpp b/WebCore/bindings/v8/custom/V8CSSStyleSheetCustom.cpp index 5dcc966..9effca3 100644 --- a/WebCore/bindings/v8/custom/V8CSSStyleSheetCustom.cpp +++ b/WebCore/bindings/v8/custom/V8CSSStyleSheetCustom.cpp @@ -31,6 +31,7 @@ #include "config.h" #include "V8CSSStyleSheet.h" +#include "V8DOMWrapper.h" #include "V8Node.h" namespace WebCore { @@ -43,7 +44,7 @@ v8::Handle<v8::Value> toV8(CSSStyleSheet* impl) // Add a hidden reference from stylesheet object to its owner node. Node* ownerNode = impl->ownerNode(); if (ownerNode && !wrapper.IsEmpty()) - wrapper->SetInternalField(V8CSSStyleSheet::ownerNodeIndex, toV8(ownerNode)); + V8DOMWrapper::setHiddenReference(wrapper, toV8(ownerNode)); return wrapper; } diff --git a/WebCore/bindings/v8/custom/V8CSSValueCustom.cpp b/WebCore/bindings/v8/custom/V8CSSValueCustom.cpp index b06bc3c..601a62a 100644 --- a/WebCore/bindings/v8/custom/V8CSSValueCustom.cpp +++ b/WebCore/bindings/v8/custom/V8CSSValueCustom.cpp @@ -33,9 +33,12 @@ #include "V8CSSPrimitiveValue.h" #include "V8CSSValueList.h" +#include "V8WebKitCSSTransformValue.h" + +#if ENABLE(SVG) #include "V8SVGColor.h" #include "V8SVGPaint.h" -#include "V8WebKitCSSTransformValue.h" +#endif namespace WebCore { diff --git a/WebCore/bindings/v8/custom/V8CanvasRenderingContext2DCustom.cpp b/WebCore/bindings/v8/custom/V8CanvasRenderingContext2DCustom.cpp index 9a05d72..26fc626 100644 --- a/WebCore/bindings/v8/custom/V8CanvasRenderingContext2DCustom.cpp +++ b/WebCore/bindings/v8/custom/V8CanvasRenderingContext2DCustom.cpp @@ -98,362 +98,4 @@ void V8CanvasRenderingContext2D::fillStyleAccessorSetter(v8::Local<v8::String> n impl->setFillStyle(toCanvasStyle(value)); } -// TODO: SetStrokeColor and SetFillColor are similar except function names, -// consolidate them into one. -v8::Handle<v8::Value> V8CanvasRenderingContext2D::setStrokeColorCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.CanvasRenderingContext2D.setStrokeColor()"); - CanvasRenderingContext2D* context = V8CanvasRenderingContext2D::toNative(args.Holder()); - switch (args.Length()) { - case 1: - if (args[0]->IsString()) - context->setStrokeColor(toWebCoreString(args[0])); - else - context->setStrokeColor(toFloat(args[0])); - break; - case 2: - if (args[0]->IsString()) - context->setStrokeColor(toWebCoreString(args[0]), toFloat(args[1])); - else - context->setStrokeColor(toFloat(args[0]), toFloat(args[1])); - break; - case 4: - context->setStrokeColor(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toFloat(args[3])); - break; - case 5: - context->setStrokeColor(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4])); - break; - default: - V8Proxy::throwError(V8Proxy::SyntaxError, "setStrokeColor: Invalid number of arguments"); - break; - } - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8CanvasRenderingContext2D::setFillColorCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.CanvasRenderingContext2D.setFillColor()"); - CanvasRenderingContext2D* context = V8CanvasRenderingContext2D::toNative(args.Holder()); - switch (args.Length()) { - case 1: - if (args[0]->IsString()) - context->setFillColor(toWebCoreString(args[0])); - else - context->setFillColor(toFloat(args[0])); - break; - case 2: - if (args[0]->IsString()) - context->setFillColor(toWebCoreString(args[0]), toFloat(args[1])); - else - context->setFillColor(toFloat(args[0]), toFloat(args[1])); - break; - case 4: - context->setFillColor(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toFloat(args[3])); - break; - case 5: - context->setFillColor(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4])); - break; - default: - V8Proxy::throwError(V8Proxy::SyntaxError, "setFillColor: Invalid number of arguments"); - break; - } - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8CanvasRenderingContext2D::strokeRectCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.CanvasRenderingContext2D.strokeRect()"); - CanvasRenderingContext2D* context = V8CanvasRenderingContext2D::toNative(args.Holder()); - if (args.Length() == 5) - context->strokeRect(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4])); - else if (args.Length() == 4) - context->strokeRect(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toFloat(args[3])); - else { - V8Proxy::setDOMException(INDEX_SIZE_ERR); - return notHandledByInterceptor(); - } - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8CanvasRenderingContext2D::setShadowCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.CanvasRenderingContext2D.setShadow()"); - CanvasRenderingContext2D* context = V8CanvasRenderingContext2D::toNative(args.Holder()); - - switch (args.Length()) { - case 3: - context->setShadow(toFloat(args[0]), toFloat(args[1]), toFloat(args[2])); - break; - case 4: - if (args[3]->IsString()) - context->setShadow(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toWebCoreString(args[3])); - else - context->setShadow(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toFloat(args[3])); - break; - case 5: - if (args[3]->IsString()) - context->setShadow(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toWebCoreString(args[3]), toFloat(args[4])); - else - context->setShadow(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4])); - break; - case 7: - context->setShadow(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4]), toFloat(args[5]), toFloat(args[6])); - break; - case 8: - context->setShadow(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4]), toFloat(args[5]), toFloat(args[6]), toFloat(args[7])); - break; - default: - V8Proxy::throwError(V8Proxy::SyntaxError, "setShadow: Invalid number of arguments"); - break; - } - - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8CanvasRenderingContext2D::drawImageCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.CanvasRenderingContext2D.drawImage()"); - CanvasRenderingContext2D* context = V8CanvasRenderingContext2D::toNative(args.Holder()); - - v8::Handle<v8::Value> arg = args[0]; - - if (V8HTMLImageElement::HasInstance(arg)) { - ExceptionCode ec = 0; - HTMLImageElement* imageElement = V8HTMLImageElement::toNative(v8::Handle<v8::Object>::Cast(arg)); - switch (args.Length()) { - case 3: - context->drawImage(imageElement, toFloat(args[1]), toFloat(args[2])); - break; - case 5: - context->drawImage(imageElement, toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4]), ec); - if (ec != 0) { - V8Proxy::setDOMException(ec); - return notHandledByInterceptor(); - } - break; - case 9: - context->drawImage(imageElement, - FloatRect(toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4])), - FloatRect(toFloat(args[5]), toFloat(args[6]), toFloat(args[7]), toFloat(args[8])), - ec); - if (ec != 0) { - V8Proxy::setDOMException(ec); - return notHandledByInterceptor(); - } - break; - default: - return throwError("drawImage: Invalid number of arguments", V8Proxy::SyntaxError); - } - return v8::Undefined(); - } - - // HTMLCanvasElement - if (V8HTMLCanvasElement::HasInstance(arg)) { - ExceptionCode ec = 0; - HTMLCanvasElement* canvasElement = V8HTMLCanvasElement::toNative(v8::Handle<v8::Object>::Cast(arg)); - switch (args.Length()) { - case 3: - context->drawImage(canvasElement, toFloat(args[1]), toFloat(args[2])); - break; - case 5: - context->drawImage(canvasElement, toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4]), ec); - if (ec != 0) { - V8Proxy::setDOMException(ec); - return notHandledByInterceptor(); - } - break; - case 9: - context->drawImage(canvasElement, - FloatRect(toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4])), - FloatRect(toFloat(args[5]), toFloat(args[6]), toFloat(args[7]), toFloat(args[8])), - ec); - if (ec != 0) { - V8Proxy::setDOMException(ec); - return notHandledByInterceptor(); - } - break; - default: - return throwError("drawImage: Invalid number of arguments", V8Proxy::SyntaxError); - } - return v8::Undefined(); - } - -#if ENABLE(VIDEO) - // HTMLVideoElement - if (V8HTMLVideoElement::HasInstance(arg)) { - ExceptionCode ec = 0; - HTMLVideoElement* videoElement = V8HTMLVideoElement::toNative(v8::Handle<v8::Object>::Cast(arg)); - switch (args.Length()) { - case 3: - context->drawImage(videoElement, toFloat(args[1]), toFloat(args[2])); - break; - case 5: - context->drawImage(videoElement, toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4]), ec); - if (ec != 0) { - V8Proxy::setDOMException(ec); - return notHandledByInterceptor(); - } - break; - case 9: - context->drawImage(videoElement, - FloatRect(toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4])), - FloatRect(toFloat(args[5]), toFloat(args[6]), toFloat(args[7]), toFloat(args[8])), - ec); - if (ec != 0) { - V8Proxy::setDOMException(ec); - return notHandledByInterceptor(); - } - break; - default: - return throwError("drawImage: Invalid number of arguments", V8Proxy::SyntaxError); - } - return v8::Undefined(); - } -#endif - - V8Proxy::setDOMException(TYPE_MISMATCH_ERR); - return notHandledByInterceptor(); -} - - -v8::Handle<v8::Value> V8CanvasRenderingContext2D::drawImageFromRectCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.CanvasRenderingContext2D.drawImageFromRect()"); - CanvasRenderingContext2D* context = V8CanvasRenderingContext2D::toNative(args.Holder()); - - v8::Handle<v8::Value> arg = args[0]; - - if (V8HTMLImageElement::HasInstance(arg)) { - HTMLImageElement* imageElement = V8HTMLImageElement::toNative(v8::Handle<v8::Object>::Cast(arg)); - context->drawImageFromRect(imageElement, toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4]), toFloat(args[5]), toFloat(args[6]), toFloat(args[7]), toFloat(args[8]), toWebCoreString(args[9])); - } else - V8Proxy::throwError(V8Proxy::TypeError, "drawImageFromRect: Invalid type of arguments"); - - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8CanvasRenderingContext2D::createPatternCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.CanvasRenderingContext2D.createPattern()"); - CanvasRenderingContext2D* context = V8CanvasRenderingContext2D::toNative(args.Holder()); - - v8::Handle<v8::Value> arg = args[0]; - - if (V8HTMLImageElement::HasInstance(arg)) { - HTMLImageElement* imageElement = V8HTMLImageElement::toNative(v8::Handle<v8::Object>::Cast(arg)); - ExceptionCode ec = 0; - RefPtr<CanvasPattern> pattern = context->createPattern(imageElement, toWebCoreStringWithNullCheck(args[1]), ec); - if (ec != 0) { - V8Proxy::setDOMException(ec); - return notHandledByInterceptor(); - } - return toV8(pattern.release()); - } - - if (V8HTMLCanvasElement::HasInstance(arg)) { - HTMLCanvasElement* canvasElement = V8HTMLCanvasElement::toNative(v8::Handle<v8::Object>::Cast(arg)); - ExceptionCode ec = 0; - RefPtr<CanvasPattern> pattern = context->createPattern(canvasElement, toWebCoreStringWithNullCheck(args[1]), ec); - if (ec != 0) { - V8Proxy::setDOMException(ec); - return notHandledByInterceptor(); - } - return toV8(pattern.release()); - } - - V8Proxy::setDOMException(TYPE_MISMATCH_ERR); - return notHandledByInterceptor(); -} - -v8::Handle<v8::Value> V8CanvasRenderingContext2D::fillTextCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.CanvasRenderingContext2D.fillText()"); - - CanvasRenderingContext2D* context = V8CanvasRenderingContext2D::toNative(args.Holder()); - - // Two forms: - // * fillText(text, x, y) - // * fillText(text, x, y, maxWidth) - if (args.Length() < 3 || args.Length() > 4) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - - String text = toWebCoreString(args[0]); - float x = toFloat(args[1]); - float y = toFloat(args[2]); - - if (args.Length() == 4) { - float maxWidth = toFloat(args[3]); - context->fillText(text, x, y, maxWidth); - } else - context->fillText(text, x, y); - - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8CanvasRenderingContext2D::strokeTextCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.CanvasRenderingContext2D.strokeText()"); - CanvasRenderingContext2D* context = V8CanvasRenderingContext2D::toNative(args.Holder()); - - // Two forms: - // * strokeText(text, x, y) - // * strokeText(text, x, y, maxWidth) - if (args.Length() < 3 || args.Length() > 4) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - - String text = toWebCoreString(args[0]); - float x = toFloat(args[1]); - float y = toFloat(args[2]); - - if (args.Length() == 4) { - float maxWidth = toFloat(args[3]); - context->strokeText(text, x, y, maxWidth); - } else - context->strokeText(text, x, y); - - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8CanvasRenderingContext2D::putImageDataCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.CanvasRenderingContext2D.putImageData()"); - - // Two froms: - // * putImageData(ImageData, x, y) - // * putImageData(ImageData, x, y, dirtyX, dirtyY, dirtyWidth, dirtyHeight) - if (args.Length() != 3 && args.Length() != 7) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - - CanvasRenderingContext2D* context = V8CanvasRenderingContext2D::toNative(args.Holder()); - - ImageData* imageData = 0; - - // Need to check that the argument is of the correct type, since - // toNative() expects it to be correct. If the argument was incorrect - // we leave it null, and putImageData() will throw the correct exception - // (TYPE_MISMATCH_ERR). - if (V8DOMWrapper::isWrapperOfType(args[0], V8ClassIndex::IMAGEDATA)) - imageData = V8ImageData::toNative(v8::Handle<v8::Object>::Cast(args[0])); - - ExceptionCode ec = 0; - - if (args.Length() == 7) - context->putImageData(imageData, toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4]), toFloat(args[5]), toFloat(args[6]), ec); - else - context->putImageData(imageData, toFloat(args[1]), toFloat(args[2]), ec); - - if (ec != 0) { - V8Proxy::setDOMException(ec); - return notHandledByInterceptor(); - } - - return v8::Undefined(); -} - } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8ConsoleCustom.cpp b/WebCore/bindings/v8/custom/V8ConsoleCustom.cpp new file mode 100644 index 0000000..9026420 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8ConsoleCustom.cpp @@ -0,0 +1,58 @@ +/* + * 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 "V8Console.h" + +#include "Console.h" +#include "ScriptProfile.h" +#include "V8Binding.h" +#include "V8Proxy.h" +#include "V8ScriptProfile.h" + +namespace WebCore { + +typedef Vector<RefPtr<ScriptProfile> > ProfilesArray; + +v8::Handle<v8::Value> V8Console::profilesAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.Console.profilesAccessorGetter"); + Console* imp = V8Console::toNative(info.Holder()); + const ProfilesArray& profiles = imp->profiles(); + v8::Handle<v8::Array> result = v8::Array::New(profiles.size()); + int index = 0; + ProfilesArray::const_iterator end = profiles.end(); + for (ProfilesArray::const_iterator iter = profiles.begin(); iter != end; ++iter) + result->Set(v8::Integer::New(index++), toV8(iter->get())); + return result; +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8CustomBinding.h b/WebCore/bindings/v8/custom/V8CustomBinding.h deleted file mode 100644 index e69de29..0000000 --- a/WebCore/bindings/v8/custom/V8CustomBinding.h +++ /dev/null diff --git a/WebCore/bindings/v8/custom/V8CustomIDBCallbacks.h b/WebCore/bindings/v8/custom/V8CustomIDBCallbacks.h new file mode 100644 index 0000000..1517f15 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8CustomIDBCallbacks.h @@ -0,0 +1,123 @@ +/* + * 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 V8CustomIDBCallbacks_h +#define V8CustomIDBCallbacks_h + +#include "Document.h" +#include "Frame.h" +#include "IDBDatabaseError.h" +#include "V8CustomVoidCallback.h" +#include "V8IDBDatabaseError.h" +#include "WorldContextHandle.h" +#include <v8.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/RefPtr.h> + +#if ENABLE(INDEXED_DATABASE) + +namespace WebCore { + +// FIXME: Maybe split common parts into a base class. +template <typename ResultType, typename ResultWrapperType> +class V8CustomIDBCallbacks : public IDBCallbacks<ResultType> { +public: + static PassRefPtr<V8CustomIDBCallbacks> create(v8::Local<v8::Value> onSuccess, v8::Local<v8::Value> onError, ScriptExecutionContext* scriptExecutionContext) + { + return adoptRef(new V8CustomIDBCallbacks(onSuccess, onError, scriptExecutionContext)); + } + + virtual ~V8CustomIDBCallbacks() + { + m_onSuccess.Dispose(); + m_onError.Dispose(); + } + + // FIXME: Handle suspend/resume correctly. + +private: + V8CustomIDBCallbacks(v8::Local<v8::Value> onSuccess, v8::Local<v8::Value> onError, ScriptExecutionContext* scriptExecutionContext) + : IDBCallbacks<ResultType>(scriptExecutionContext, this) + , m_onSuccess(onSuccess->IsObject() ? v8::Persistent<v8::Object>::New(onSuccess->ToObject()) : v8::Persistent<v8::Object>()) + , m_onError(onError->IsObject() ? v8::Persistent<v8::Object>::New(onError->ToObject()) : v8::Persistent<v8::Object>()) + , m_worldContext(UseCurrentWorld) + { + } + + template <typename Type> + void onEvent(v8::Persistent<v8::Object> callback, PassRefPtr<Type> value) + { + if (!ActiveDOMObject::scriptExecutionContext()) + return; + if (callback.IsEmpty()) + return; + + v8::HandleScope handleScope; + v8::Handle<v8::Context> context = toV8Context(ActiveDOMObject::scriptExecutionContext(), m_worldContext); + if (context.IsEmpty()) + return; + + v8::Context::Scope scope(context); + v8::Handle<v8::Value> argv[] = { + toV8(value) + }; + + // FIXME: Make this work for workers. + ASSERT(ActiveDOMObject::scriptExecutionContext()->isDocument()); + RefPtr<Frame> protector(static_cast<Document*>(ActiveDOMObject::scriptExecutionContext())->frame()); + + bool callbackReturnValue = false; + // FIXME: Do we care if this thing returns true (i.e. it raised an exception)? + invokeCallback(callback, 1, argv, callbackReturnValue); + } + + virtual void onSuccessAsync(PassRefPtr<ResultType> result) + { + onEvent(m_onSuccess, ResultWrapperType::create(result)); + } + + virtual void onErrorAsync(PassRefPtr<IDBDatabaseError> error) + { + onEvent(m_onError, error); + } + + // FIXME: Use OwnHandles. + v8::Persistent<v8::Object> m_onSuccess; + v8::Persistent<v8::Object> m_onError; + + WorldContextHandle m_worldContext; +}; + +} + +#endif + +#endif // V8CustomIDBCallbacks_h diff --git a/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.cpp b/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.cpp index d30b95a..df0cc53 100644 --- a/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.cpp +++ b/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.cpp @@ -35,6 +35,7 @@ #include "V8CustomSQLStatementCallback.h" #include "Frame.h" +#include "ScriptExecutionContext.h" #include "V8CustomVoidCallback.h" #include "V8SQLResultSet.h" #include "V8SQLTransaction.h" @@ -44,6 +45,7 @@ namespace WebCore { V8CustomSQLStatementCallback::V8CustomSQLStatementCallback(v8::Local<v8::Object> callback, Frame* frame) : m_callback(v8::Persistent<v8::Object>::New(callback)) , m_frame(frame) + , m_worldContext(UseCurrentWorld) { } @@ -52,15 +54,15 @@ V8CustomSQLStatementCallback::~V8CustomSQLStatementCallback() m_callback.Dispose(); } -void V8CustomSQLStatementCallback::handleEvent(SQLTransaction* transaction, SQLResultSet* resultSet, bool& raisedException) +void V8CustomSQLStatementCallback::handleEvent(ScriptExecutionContext* context, SQLTransaction* transaction, SQLResultSet* resultSet, bool& raisedException) { v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::context(m_frame.get()); - if (context.IsEmpty()) + v8::Handle<v8::Context> v8Context = toV8Context(context, m_worldContext); + if (v8Context.IsEmpty()) return; - v8::Context::Scope scope(context); + v8::Context::Scope scope(v8Context); v8::Handle<v8::Value> argv[] = { toV8(transaction), @@ -77,4 +79,3 @@ void V8CustomSQLStatementCallback::handleEvent(SQLTransaction* transaction, SQLR } // namespace WebCore #endif - diff --git a/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.h b/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.h index 58ee943..31f53e4 100644 --- a/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.h +++ b/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.h @@ -34,9 +34,9 @@ #if ENABLE(DATABASE) #include "SQLStatementCallback.h" +#include "WorldContextHandle.h" #include <v8.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefPtr.h> +#include <wtf/Forward.h> namespace WebCore { @@ -51,12 +51,13 @@ public: } virtual ~V8CustomSQLStatementCallback(); - virtual void handleEvent(SQLTransaction*, SQLResultSet*, bool& raisedException); + virtual void handleEvent(ScriptExecutionContext*, SQLTransaction*, SQLResultSet*, bool& raisedException); private: V8CustomSQLStatementCallback(v8::Local<v8::Object>, Frame*); v8::Persistent<v8::Object> m_callback; RefPtr<Frame> m_frame; + WorldContextHandle m_worldContext; }; } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp b/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp index f733ede..2545f24 100644 --- a/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp +++ b/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp @@ -35,6 +35,7 @@ #include "V8CustomSQLStatementErrorCallback.h" #include "Frame.h" +#include "ScriptExecutionContext.h" #include "V8CustomVoidCallback.h" #include "V8SQLError.h" #include "V8SQLTransaction.h" @@ -44,6 +45,7 @@ namespace WebCore { V8CustomSQLStatementErrorCallback::V8CustomSQLStatementErrorCallback(v8::Local<v8::Object> callback, Frame* frame) : m_callback(v8::Persistent<v8::Object>::New(callback)) , m_frame(frame) + , m_worldContext(UseCurrentWorld) { } @@ -52,15 +54,15 @@ V8CustomSQLStatementErrorCallback::~V8CustomSQLStatementErrorCallback() m_callback.Dispose(); } -bool V8CustomSQLStatementErrorCallback::handleEvent(SQLTransaction* transaction, SQLError* error) +bool V8CustomSQLStatementErrorCallback::handleEvent(ScriptExecutionContext* context, SQLTransaction* transaction, SQLError* error) { v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::context(m_frame.get()); - if (context.IsEmpty()) + v8::Handle<v8::Context> v8Context = toV8Context(context, m_worldContext); + if (v8Context.IsEmpty()) return true; - v8::Context::Scope scope(context); + v8::Context::Scope scope(v8Context); v8::Handle<v8::Value> argv[] = { toV8(transaction), @@ -75,7 +77,7 @@ bool V8CustomSQLStatementErrorCallback::handleEvent(SQLTransaction* transaction, // statement, if any, or onto the next overall step otherwise. Otherwise, // the error callback did not return false, or there was no error callback. // Jump to the last step in the overall steps. - return invokeCallbackTreatOnlyExplicitFalseAsFalse(m_callback, 2, argv, callbackReturnValue) || callbackReturnValue; + return invokeCallback(m_callback, 2, argv, callbackReturnValue) || callbackReturnValue; } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.h b/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.h index 685efc6..c3d7f79 100644 --- a/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.h +++ b/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.h @@ -34,8 +34,7 @@ #if ENABLE(DATABASE) #include "SQLStatementErrorCallback.h" - -#include "SQLStatementErrorCallback.h" +#include "WorldContextHandle.h" #include <v8.h> #include <wtf/PassRefPtr.h> #include <wtf/RefPtr.h> @@ -53,12 +52,13 @@ public: } virtual ~V8CustomSQLStatementErrorCallback(); - virtual bool handleEvent(SQLTransaction*, SQLError*); + virtual bool handleEvent(ScriptExecutionContext*, SQLTransaction*, SQLError*); private: V8CustomSQLStatementErrorCallback(v8::Local<v8::Object>, Frame*); v8::Persistent<v8::Object> m_callback; RefPtr<Frame> m_frame; + WorldContextHandle m_worldContext; }; } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.cpp b/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.cpp index 68002d7..efe415c 100644 --- a/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.cpp +++ b/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.cpp @@ -35,6 +35,7 @@ #include "V8CustomSQLTransactionCallback.h" #include "Frame.h" +#include "ScriptExecutionContext.h" #include "V8CustomVoidCallback.h" #include "V8SQLTransaction.h" @@ -43,6 +44,7 @@ namespace WebCore { V8CustomSQLTransactionCallback::V8CustomSQLTransactionCallback(v8::Local<v8::Object> callback, Frame* frame) : m_callback(v8::Persistent<v8::Object>::New(callback)) , m_frame(frame) + , m_worldContext(UseCurrentWorld) { } @@ -52,15 +54,15 @@ V8CustomSQLTransactionCallback::~V8CustomSQLTransactionCallback() } -void V8CustomSQLTransactionCallback::handleEvent(SQLTransaction* transaction, bool& raisedException) +void V8CustomSQLTransactionCallback::handleEvent(ScriptExecutionContext* context, SQLTransaction* transaction, bool& raisedException) { v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::context(m_frame.get()); - if (context.IsEmpty()) + v8::Handle<v8::Context> v8Context = toV8Context(context, m_worldContext); + if (v8Context.IsEmpty()) return; - v8::Context::Scope scope(context); + v8::Context::Scope scope(v8Context); v8::Handle<v8::Value> argv[] = { toV8(transaction) @@ -79,4 +81,3 @@ void V8CustomSQLTransactionCallback::handleEvent(SQLTransaction* transaction, bo } // namespace WebCore #endif - diff --git a/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.h b/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.h index 665404d..60ad529 100644 --- a/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.h +++ b/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.h @@ -34,9 +34,9 @@ #if ENABLE(DATABASE) #include "SQLTransactionCallback.h" +#include "WorldContextHandle.h" #include <v8.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefPtr.h> +#include <wtf/Forward.h> namespace WebCore { @@ -51,12 +51,13 @@ public: } virtual ~V8CustomSQLTransactionCallback(); - virtual void handleEvent(SQLTransaction*, bool& raisedException); + virtual void handleEvent(ScriptExecutionContext*, SQLTransaction*, bool& raisedException); private: V8CustomSQLTransactionCallback(v8::Local<v8::Object>, Frame*); v8::Persistent<v8::Object> m_callback; RefPtr<Frame> m_frame; + WorldContextHandle m_worldContext; }; } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.cpp b/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.cpp index cf5a0ef..1ef711a 100644 --- a/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.cpp +++ b/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.cpp @@ -35,6 +35,7 @@ #include "V8CustomSQLTransactionErrorCallback.h" #include "Frame.h" +#include "ScriptExecutionContext.h" #include "V8CustomVoidCallback.h" #include "V8SQLError.h" @@ -43,6 +44,7 @@ namespace WebCore { V8CustomSQLTransactionErrorCallback::V8CustomSQLTransactionErrorCallback(v8::Local<v8::Object> callback, Frame* frame) : m_callback(v8::Persistent<v8::Object>::New(callback)) , m_frame(frame) + , m_worldContext(UseCurrentWorld) { } @@ -51,15 +53,15 @@ V8CustomSQLTransactionErrorCallback::~V8CustomSQLTransactionErrorCallback() m_callback.Dispose(); } -void V8CustomSQLTransactionErrorCallback::handleEvent(SQLError* error) +void V8CustomSQLTransactionErrorCallback::handleEvent(ScriptExecutionContext* context, SQLError* error) { v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::context(m_frame.get()); - if (context.IsEmpty()) + v8::Handle<v8::Context> v8Context = toV8Context(context, m_worldContext); + if (v8Context.IsEmpty()) return; - v8::Context::Scope scope(context); + v8::Context::Scope scope(v8Context); v8::Handle<v8::Value> argv[] = { toV8(error) @@ -75,4 +77,3 @@ void V8CustomSQLTransactionErrorCallback::handleEvent(SQLError* error) } // namespace WebCore #endif - diff --git a/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.h b/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.h index 0387deb..72e9e7a 100644 --- a/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.h +++ b/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.h @@ -34,9 +34,9 @@ #if ENABLE(DATABASE) #include "SQLTransactionErrorCallback.h" +#include "WorldContextHandle.h" #include <v8.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefPtr.h> +#include <wtf/Forward.h> namespace WebCore { @@ -51,13 +51,14 @@ public: } virtual ~V8CustomSQLTransactionErrorCallback(); - virtual void handleEvent(SQLError*); + virtual void handleEvent(ScriptExecutionContext*, SQLError*); private: V8CustomSQLTransactionErrorCallback(v8::Local<v8::Object>, Frame*); v8::Persistent<v8::Object> m_callback; RefPtr<Frame> m_frame; + WorldContextHandle m_worldContext; }; } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8CustomVoidCallback.cpp b/WebCore/bindings/v8/custom/V8CustomVoidCallback.cpp index 8c69e76..f4ea62a 100644 --- a/WebCore/bindings/v8/custom/V8CustomVoidCallback.cpp +++ b/WebCore/bindings/v8/custom/V8CustomVoidCallback.cpp @@ -29,10 +29,10 @@ */ #include "config.h" -#include "V8Binding.h" #include "V8CustomVoidCallback.h" #include "Frame.h" +#include "V8Binding.h" namespace WebCore { @@ -64,7 +64,7 @@ void V8CustomVoidCallback::handleEvent() invokeCallback(m_callback, 0, 0, callbackReturnValue); } -static bool invokeCallbackHelper(v8::Persistent<v8::Object> callback, int argc, v8::Handle<v8::Value> argv[], v8::Handle<v8::Value>& returnValue) +bool invokeCallback(v8::Persistent<v8::Object> callback, int argc, v8::Handle<v8::Value> argv[], bool& callbackReturnValue) { v8::TryCatch exceptionCatcher; @@ -73,9 +73,8 @@ static bool invokeCallbackHelper(v8::Persistent<v8::Object> callback, int argc, callbackFunction = v8::Local<v8::Function>::New(v8::Persistent<v8::Function>::Cast(callback)); } else if (callback->IsObject()) { v8::Local<v8::Value> handleEventFunction = callback->Get(v8::String::NewSymbol("handleEvent")); - if (handleEventFunction->IsFunction()) { + if (handleEventFunction->IsFunction()) callbackFunction = v8::Local<v8::Function>::Cast(handleEventFunction); - } } else return false; @@ -87,7 +86,8 @@ static bool invokeCallbackHelper(v8::Persistent<v8::Object> callback, int argc, V8Proxy* proxy = V8Proxy::retrieve(); ASSERT(proxy); - returnValue = proxy->callFunction(callbackFunction, thisObject, argc, argv); + v8::Handle<v8::Value> result = proxy->callFunction(callbackFunction, thisObject, argc, argv); + callbackReturnValue = !result.IsEmpty() && result->BooleanValue(); if (exceptionCatcher.HasCaught()) { v8::Local<v8::Message> message = exceptionCatcher.Message(); @@ -98,20 +98,4 @@ static bool invokeCallbackHelper(v8::Persistent<v8::Object> callback, int argc, return false; } -bool invokeCallback(v8::Persistent<v8::Object> callback, int argc, v8::Handle<v8::Value> argv[], bool& callbackReturnValue) -{ - v8::Handle<v8::Value> returnValue; - bool result = invokeCallbackHelper(callback, argc, argv, returnValue); - callbackReturnValue = !returnValue.IsEmpty() && returnValue->IsBoolean() && returnValue->BooleanValue(); - return result; -} - -bool invokeCallbackTreatOnlyExplicitFalseAsFalse(v8::Persistent<v8::Object> callback, int argc, v8::Handle<v8::Value> argv[], bool& callbackReturnValue) -{ - v8::Handle<v8::Value> returnValue; - bool result = invokeCallbackHelper(callback, argc, argv, returnValue); - callbackReturnValue = !returnValue.IsEmpty() && !returnValue->IsFalse(); - return result; -} - } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8CustomVoidCallback.h b/WebCore/bindings/v8/custom/V8CustomVoidCallback.h index 6b7b3e8..586296b 100644 --- a/WebCore/bindings/v8/custom/V8CustomVoidCallback.h +++ b/WebCore/bindings/v8/custom/V8CustomVoidCallback.h @@ -60,7 +60,6 @@ private: // Returns false if callback failed (null, wrong type, or threw exception). bool invokeCallback(v8::Persistent<v8::Object> callback, int argc, v8::Handle<v8::Value> argv[], bool& callbackReturnValue); -bool invokeCallbackTreatOnlyExplicitFalseAsFalse(v8::Persistent<v8::Object> callback, int argc, v8::Handle<v8::Value> argv[], bool& callbackReturnValue); } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.cpp b/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.cpp index e45cba0..01448d9 100644 --- a/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.cpp +++ b/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.cpp @@ -38,14 +38,13 @@ namespace WebCore { -PassRefPtr<V8CustomXPathNSResolver> V8CustomXPathNSResolver::create(V8Proxy* proxy, v8::Handle<v8::Object> resolver) +PassRefPtr<V8CustomXPathNSResolver> V8CustomXPathNSResolver::create(v8::Handle<v8::Object> resolver) { - return adoptRef(new V8CustomXPathNSResolver(proxy, resolver)); + return adoptRef(new V8CustomXPathNSResolver(resolver)); } -V8CustomXPathNSResolver::V8CustomXPathNSResolver(V8Proxy* proxy, v8::Handle<v8::Object> resolver) - : m_proxy(proxy) - , m_resolver(resolver) +V8CustomXPathNSResolver::V8CustomXPathNSResolver(v8::Handle<v8::Object> resolver) + : m_resolver(resolver) { } @@ -55,14 +54,6 @@ V8CustomXPathNSResolver::~V8CustomXPathNSResolver() String V8CustomXPathNSResolver::lookupNamespaceURI(const String& prefix) { - V8Proxy* proxy = m_proxy; - - if (!proxy) { - proxy = V8Proxy::retrieve(); - if (!proxy) - return String(); - } - v8::Handle<v8::Function> lookupNamespaceURIFunc; v8::Handle<v8::String> lookupNamespaceURIName = v8::String::New("lookupNamespaceURI"); @@ -74,8 +65,10 @@ String V8CustomXPathNSResolver::lookupNamespaceURI(const String& prefix) } if (lookupNamespaceURIFunc.IsEmpty() && !m_resolver->IsFunction()) { - Frame* frame = proxy->frame(); - logInfo(frame, "XPathNSResolver does not have a lookupNamespaceURI method.", String()); + if (V8Proxy* proxy = V8Proxy::retrieve()) { + if (Frame* frame = proxy->frame()) + logInfo(frame, "XPathNSResolver does not have a lookupNamespaceURI method.", String()); + } return String(); } @@ -87,7 +80,7 @@ String V8CustomXPathNSResolver::lookupNamespaceURI(const String& prefix) v8::Handle<v8::Value> argv[argc] = { v8String(prefix) }; v8::Handle<v8::Function> function = lookupNamespaceURIFunc.IsEmpty() ? v8::Handle<v8::Function>::Cast(m_resolver) : lookupNamespaceURIFunc; - v8::Handle<v8::Value> retval = proxy->callFunction(function, m_resolver, argc, argv); + v8::Handle<v8::Value> retval = V8Proxy::callFunctionWithoutFrame(function, m_resolver, argc, argv); // Eat exceptions from namespace resolver and return an empty string. This will most likely cause NAMESPACE_ERR. if (try_catch.HasCaught()) diff --git a/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.h b/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.h index 15ac27d..cf84438 100644 --- a/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.h +++ b/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.h @@ -49,15 +49,14 @@ class V8Proxy; // must not exceed the lifetime of the passed handle. class V8CustomXPathNSResolver : public XPathNSResolver { public: - static PassRefPtr<V8CustomXPathNSResolver> create(V8Proxy* proxy, v8::Handle<v8::Object> resolver); + static PassRefPtr<V8CustomXPathNSResolver> create(v8::Handle<v8::Object> resolver); virtual ~V8CustomXPathNSResolver(); virtual String lookupNamespaceURI(const String& prefix); private: - V8CustomXPathNSResolver(V8Proxy* proxy, v8::Handle<v8::Object> resolver); + explicit V8CustomXPathNSResolver(v8::Handle<v8::Object> resolver); - V8Proxy* m_proxy; v8::Handle<v8::Object> m_resolver; // Handle to resolver object. }; diff --git a/WebCore/bindings/v8/custom/V8DOMApplicationCacheCustom.cpp b/WebCore/bindings/v8/custom/V8DOMApplicationCacheCustom.cpp deleted file mode 100644 index 61760b3..0000000 --- a/WebCore/bindings/v8/custom/V8DOMApplicationCacheCustom.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2009 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 "V8DOMApplicationCache.h" - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - -#include "ApplicationCacheHost.h" -#include "DOMApplicationCache.h" -#include "V8Binding.h" -#include "V8Document.h" -#include "V8Proxy.h" -#include "V8Utilities.h" -#include "WorkerContextExecutionProxy.h" - -namespace WebCore { - -// Handles appcache.addEventListner(name, func, capture) method calls -v8::Handle<v8::Value> V8DOMApplicationCache::addEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOMApplicationCache.addEventListener()"); - DOMApplicationCache* appcache = V8DOMApplicationCache::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(appcache, args[1], false, ListenerFindOrCreate); - if (listener) { - createHiddenDependency(args.Holder(), args[1], cacheIndex); - String eventType = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - appcache->addEventListener(eventType, listener, useCapture); - } - return v8::Undefined(); -} - -// Handles appcache.removeEventListner(name, func, capture) method calls -v8::Handle<v8::Value> V8DOMApplicationCache::removeEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOMApplicationCache.removeEventListener()"); - DOMApplicationCache* appcache = V8DOMApplicationCache::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(appcache, args[1], false, ListenerFindOnly); - if (listener) { - removeHiddenDependency(args.Holder(), args[1], cacheIndex); - String eventType = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - appcache->removeEventListener(eventType, listener.get(), useCapture); - } - return v8::Undefined(); -} - -} // namespace WebCore - -#endif // ENABLE(OFFLINE_WEB_APPLICATIONS) diff --git a/WebCore/bindings/v8/custom/V8DOMFormDataCustom.cpp b/WebCore/bindings/v8/custom/V8DOMFormDataCustom.cpp new file mode 100644 index 0000000..8a39332 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8DOMFormDataCustom.cpp @@ -0,0 +1,65 @@ +/* + * 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 "V8DOMFormData.h" + +#include "DOMFormData.h" +#include "V8Binding.h" +#include "V8Blob.h" +#include "V8Proxy.h" +#include "V8Utilities.h" + +namespace WebCore { + +v8::Handle<v8::Value> V8DOMFormData::appendCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.FormData.append()"); + + if (args.Length() < 2) + return throwError("Not enough arguments", V8Proxy::SyntaxError); + + DOMFormData* domFormData = V8DOMFormData::toNative(args.Holder()); + + String name = toWebCoreStringWithNullCheck(args[0]); + + v8::Handle<v8::Value> arg = args[1]; + if (V8Blob::HasInstance(arg)) { + v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg); + Blob* blob = V8Blob::toNative(object); + ASSERT(blob); + domFormData->append(name, blob); + } else + domFormData->append(name, toWebCoreStringWithNullCheck(arg)); + + return v8::Undefined(); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp b/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp index 9719837..6a53a1f 100644 --- a/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp +++ b/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp @@ -31,7 +31,6 @@ #include "config.h" #include "V8DOMWindow.h" -#include "Base64.h" #include "Chrome.h" #include "Database.h" #include "DOMTimer.h" @@ -55,7 +54,13 @@ #include "V8BindingDOMWindow.h" #include "V8BindingState.h" #include "V8CustomEventListener.h" +#include "V8Database.h" +#include "V8DatabaseCallback.h" +#include "V8GCForContextDispose.h" +#include "V8HTMLAudioElementConstructor.h" #include "V8HTMLCollection.h" +#include "V8HTMLImageElementConstructor.h" +#include "V8HTMLOptionElementConstructor.h" #include "V8MessagePortCustom.h" #include "V8Node.h" #include "V8Proxy.h" @@ -135,38 +140,14 @@ v8::Handle<v8::Value> WindowSetTimeoutImpl(const v8::Arguments& args, bool singl id = DOMTimer::install(scriptContext, new ScheduledAction(V8Proxy::context(imp->frame()), functionString), timeout, singleShot); } - return v8::Integer::New(id); -} - -static bool isAscii(const String& str) -{ - for (size_t i = 0; i < str.length(); i++) { - if (str[i] > 0xFF) - return false; + // Try to do the idle notification before the timeout expires to get better + // use of any idle time. Aim for the middle of the interval for simplicity. + if (timeout > 0) { + double maximumFireInterval = static_cast<double>(timeout) / 1000 / 2; + V8GCForContextDispose::instance().notifyIdleSooner(maximumFireInterval); } - return true; -} -static v8::Handle<v8::Value> convertBase64(const String& str, bool encode) -{ - if (!isAscii(str)) { - V8Proxy::setDOMException(INVALID_CHARACTER_ERR); - return notHandledByInterceptor(); - } - - Vector<char> inputCharacters(str.length()); - for (size_t i = 0; i < str.length(); i++) - inputCharacters[i] = static_cast<char>(str[i]); - Vector<char> outputCharacters; - - if (encode) - base64Encode(inputCharacters, outputCharacters); - else { - if (!base64Decode(inputCharacters, outputCharacters)) - return throwError("Cannot decode base64", V8Proxy::GeneralError); - } - - return v8String(String(outputCharacters.data(), outputCharacters.size())); + return v8::Integer::New(id); } v8::Handle<v8::Value> V8DOMWindow::eventAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) @@ -250,7 +231,7 @@ void V8DOMWindow::openerAccessorSetter(v8::Local<v8::String> name, v8::Local<v8: v8::Handle<v8::Value> V8DOMWindow::AudioAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { DOMWindow* window = V8DOMWindow::toNative(info.Holder()); - return V8DOMWrapper::getConstructor(V8ClassIndex::AUDIO, window); + return V8DOMWrapper::getConstructor(&V8HTMLAudioElementConstructor::info, window); } #endif @@ -258,13 +239,13 @@ v8::Handle<v8::Value> V8DOMWindow::AudioAccessorGetter(v8::Local<v8::String> nam v8::Handle<v8::Value> V8DOMWindow::ImageAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { DOMWindow* window = V8DOMWindow::toNative(info.Holder()); - return V8DOMWrapper::getConstructor(V8ClassIndex::IMAGE, window); + return V8DOMWrapper::getConstructor(&V8HTMLImageElementConstructor::info, window); } v8::Handle<v8::Value> V8DOMWindow::OptionAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { DOMWindow* window = V8DOMWindow::toNative(info.Holder()); - return V8DOMWrapper::getConstructor(V8ClassIndex::OPTION, window); + return V8DOMWrapper::getConstructor(&V8HTMLOptionElementConstructor::info, window); } v8::Handle<v8::Value> V8DOMWindow::addEventListenerCallback(const v8::Arguments& args) @@ -289,11 +270,11 @@ v8::Handle<v8::Value> V8DOMWindow::addEventListenerCallback(const v8::Arguments& if (!proxy) return v8::Undefined(); - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(proxy, args[1], false, ListenerFindOrCreate); + RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(args[1], false, ListenerFindOrCreate); if (listener) { imp->addEventListener(eventType, listener, useCapture); - createHiddenDependency(args.Holder(), args[1], cacheIndex); + createHiddenDependency(args.Holder(), args[1], eventListenerCacheIndex); } return v8::Undefined(); @@ -321,11 +302,11 @@ v8::Handle<v8::Value> V8DOMWindow::removeEventListenerCallback(const v8::Argumen if (!proxy) return v8::Undefined(); - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(proxy, args[1], false, ListenerFindOnly); + RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(args[1], false, ListenerFindOnly); if (listener) { imp->removeEventListener(eventType, listener.get(), useCapture); - removeHiddenDependency(args.Holder(), args[1], cacheIndex); + removeHiddenDependency(args.Holder(), args[1], eventListenerCacheIndex); } return v8::Undefined(); @@ -339,8 +320,11 @@ v8::Handle<v8::Value> V8DOMWindow::postMessageCallback(const v8::Arguments& args DOMWindow* source = V8Proxy::retrieveFrameForCallingContext()->domWindow(); ASSERT(source->frame()); - v8::TryCatch tryCatch; - RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(args[0]); + bool didThrow = false; + RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(args[0], didThrow); + if (didThrow) + return v8::Undefined(); + MessagePortArray portArray; String targetOrigin; @@ -348,6 +332,7 @@ v8::Handle<v8::Value> V8DOMWindow::postMessageCallback(const v8::Arguments& args // postMessage(message, port, targetOrigin); // or // postMessage(message, targetOrigin); + v8::TryCatch tryCatch; if (args.Length() > 2) { if (!getMessagePortArray(args[1], portArray)) return v8::Undefined(); @@ -364,44 +349,6 @@ v8::Handle<v8::Value> V8DOMWindow::postMessageCallback(const v8::Arguments& args return throwError(ec); } -v8::Handle<v8::Value> V8DOMWindow::atobCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.DOMWindow.atob()"); - - if (args[0]->IsNull()) - return v8String(""); - String str = toWebCoreString(args[0]); - - DOMWindow* imp = V8DOMWindow::toNative(args.Holder()); - - if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true)) - return v8::Undefined(); - - if (args.Length() < 1) - return throwError("Not enough arguments", V8Proxy::SyntaxError); - - return convertBase64(str, false); -} - -v8::Handle<v8::Value> V8DOMWindow::btoaCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.DOMWindow.btoa()"); - - if (args[0]->IsNull()) - return v8String(""); - String str = toWebCoreString(args[0]); - - DOMWindow* imp = V8DOMWindow::toNative(args.Holder()); - - if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true)) - return v8::Undefined(); - - if (args.Length() < 1) - return throwError("Not enough arguments", V8Proxy::SyntaxError); - - return convertBase64(str, true); -} - // FIXME(fqian): returning string is cheating, and we should // fix this by calling toString function on the receiver. // However, V8 implements toString in JavaScript, which requires @@ -768,39 +715,33 @@ v8::Handle<v8::Value> V8DOMWindow::setIntervalCallback(const v8::Arguments& args return WindowSetTimeoutImpl(args, false); } - -void ClearTimeoutImpl(const v8::Arguments& args) +v8::Handle<v8::Value> V8DOMWindow::openDatabaseCallback(const v8::Arguments& args) { - int handle = toInt32(args[0]); + INC_STATS("DOM.DOMWindow.openDatabase"); + if (args.Length() < 4) + return v8::Undefined(); - v8::Handle<v8::Object> holder = args.Holder(); - DOMWindow* imp = V8DOMWindow::toNative(holder); + DOMWindow* imp = V8DOMWindow::toNative(args.Holder()); if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true)) - return; - ScriptExecutionContext* context = static_cast<ScriptExecutionContext*>(imp->document()); - if (!context) - return; - DOMTimer::removeById(context, handle); -} + return v8::Undefined(); + ExceptionCode ec = 0; + String name = toWebCoreString(args[0]); + String version = toWebCoreString(args[1]); + String displayName = toWebCoreString(args[2]); + unsigned long estimatedSize = args[3]->IntegerValue(); + RefPtr<DatabaseCallback> creationCallback; + if ((args.Length() >= 5) && args[4]->IsObject()) + creationCallback = V8DatabaseCallback::create(args[4], imp->frame()); -v8::Handle<v8::Value> V8DOMWindow::clearTimeoutCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.DOMWindow.clearTimeout"); - ClearTimeoutImpl(args); - return v8::Undefined(); -} + v8::Handle<v8::Value> result = toV8(imp->openDatabase(name, version, displayName, estimatedSize, creationCallback.release(), ec)); -v8::Handle<v8::Value> V8DOMWindow::clearIntervalCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.DOMWindow.clearInterval"); - ClearTimeoutImpl(args); - return v8::Undefined(); + V8Proxy::setDOMException(ec); + return result; } -bool V8DOMWindow::namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value> data) +bool V8DOMWindow::namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value>) { - ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::DOMWINDOW); v8::Handle<v8::Object> window = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), host); if (window.IsEmpty()) return false; // the frame is gone. @@ -824,9 +765,8 @@ bool V8DOMWindow::namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::V return V8BindingSecurity::canAccessFrame(V8BindingState::Only(), target, false); } -bool V8DOMWindow::indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType type, v8::Local<v8::Value> data) +bool V8DOMWindow::indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType type, v8::Local<v8::Value>) { - ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::DOMWINDOW); v8::Handle<v8::Object> window = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), host); if (window.IsEmpty()) return false; diff --git a/WebCore/bindings/v8/custom/V8DatabaseCallback.cpp b/WebCore/bindings/v8/custom/V8DatabaseCallback.cpp new file mode 100644 index 0000000..088d89f --- /dev/null +++ b/WebCore/bindings/v8/custom/V8DatabaseCallback.cpp @@ -0,0 +1,79 @@ +/* + * 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(DATABASE) + +#include "V8DatabaseCallback.h" + +#include "Frame.h" +#include "ScriptExecutionContext.h" +#include "V8CustomVoidCallback.h" +#include "V8Database.h" + +namespace WebCore { + +V8DatabaseCallback::V8DatabaseCallback(v8::Local<v8::Object> callback, Frame* frame) + : m_callback(v8::Persistent<v8::Object>::New(callback)) + , m_frame(frame) + , m_worldContext(UseCurrentWorld) +{ +} + +V8DatabaseCallback::~V8DatabaseCallback() +{ + m_callback.Dispose(); +} + +void V8DatabaseCallback::handleEvent(ScriptExecutionContext* context, Database* database) +{ + v8::HandleScope handleScope; + + v8::Handle<v8::Context> v8Context = toV8Context(context, m_worldContext); + if (v8Context.IsEmpty()) + return; + + v8::Context::Scope scope(v8Context); + + v8::Handle<v8::Value> argv[] = { + toV8(database) + }; + + // Protect the frame until the callback returns. + RefPtr<Frame> protector(m_frame); + + bool callbackReturnValue = false; + invokeCallback(m_callback, 1, argv, callbackReturnValue); +} + +} // namespace WebCore + +#endif diff --git a/WebCore/bindings/v8/custom/V8DatabaseCallback.h b/WebCore/bindings/v8/custom/V8DatabaseCallback.h new file mode 100644 index 0000000..064a9a7 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8DatabaseCallback.h @@ -0,0 +1,68 @@ +/* + * 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 V8DatabaseCallback_h +#define V8DatabaseCallback_h + +#if ENABLE(DATABASE) + +#include "DatabaseCallback.h" +#include "WorldContextHandle.h" +#include <v8.h> +#include <wtf/Forward.h> + +namespace WebCore { + +class Frame; + +class V8DatabaseCallback : public DatabaseCallback { +public: + static PassRefPtr<V8DatabaseCallback> create(v8::Local<v8::Value> value, Frame* frame) + { + ASSERT(value->IsObject()); + return adoptRef(new V8DatabaseCallback(value->ToObject(), frame)); + } + virtual ~V8DatabaseCallback(); + + virtual void handleEvent(ScriptExecutionContext*, Database*); + +private: + V8DatabaseCallback(v8::Local<v8::Object>, Frame*); + + v8::Persistent<v8::Object> m_callback; + RefPtr<Frame> m_frame; + WorldContextHandle m_worldContext; +}; + +} // namespace WebCore + +#endif + +#endif // V8DatabaseCallback_h diff --git a/WebCore/bindings/v8/custom/V8DedicatedWorkerContextCustom.cpp b/WebCore/bindings/v8/custom/V8DedicatedWorkerContextCustom.cpp index 4486dbe..8fcf9a8 100644 --- a/WebCore/bindings/v8/custom/V8DedicatedWorkerContextCustom.cpp +++ b/WebCore/bindings/v8/custom/V8DedicatedWorkerContextCustom.cpp @@ -46,7 +46,10 @@ v8::Handle<v8::Value> V8DedicatedWorkerContext::postMessageCallback(const v8::Ar { INC_STATS(L"DOM.DedicatedWorkerContext.postMessage"); DedicatedWorkerContext* workerContext = V8DedicatedWorkerContext::toNative(args.Holder()); - RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(args[0]); + bool didThrow = false; + RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(args[0], didThrow); + if (didThrow) + return v8::Undefined(); MessagePortArray portArray; if (args.Length() > 1) { if (!getMessagePortArray(args[1], portArray)) diff --git a/WebCore/bindings/v8/custom/V8DocumentCustom.cpp b/WebCore/bindings/v8/custom/V8DocumentCustom.cpp index 8968707..9fa9f80 100644 --- a/WebCore/bindings/v8/custom/V8DocumentCustom.cpp +++ b/WebCore/bindings/v8/custom/V8DocumentCustom.cpp @@ -46,11 +46,16 @@ #include "V8IsolatedContext.h" #include "V8Node.h" #include "V8Proxy.h" -#include "V8SVGDocument.h" +#if ENABLE(3D_CANVAS) #include "V8WebGLRenderingContext.h" +#endif #include "V8XPathNSResolver.h" #include "V8XPathResult.h" +#if ENABLE(SVG) +#include "V8SVGDocument.h" +#endif + #include <wtf/RefPtr.h> namespace WebCore { @@ -67,7 +72,7 @@ v8::Handle<v8::Value> V8Document::evaluateCallback(const v8::Arguments& args) if (V8Node::HasInstance(args[1])) contextNode = V8Node::toNative(v8::Handle<v8::Object>::Cast(args[1])); - RefPtr<XPathNSResolver> resolver = V8DOMWrapper::getXPathNSResolver(args[2], V8Proxy::retrieve(V8Proxy::retrieveFrameForCallingContext())); + RefPtr<XPathNSResolver> resolver = V8DOMWrapper::getXPathNSResolver(args[2]); if (!resolver && !args[2]->IsNull() && !args[2]->IsUndefined()) return throwError(TYPE_MISMATCH_ERR); diff --git a/WebCore/bindings/v8/custom/V8ElementCustom.cpp b/WebCore/bindings/v8/custom/V8ElementCustom.cpp index 86f134e..8256110 100644 --- a/WebCore/bindings/v8/custom/V8ElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8ElementCustom.cpp @@ -45,7 +45,10 @@ #include "V8BindingState.h" #include "V8HTMLElement.h" #include "V8Proxy.h" + +#if ENABLE(SVG) #include "V8SVGElement.h" +#endif #include <wtf/RefPtr.h> diff --git a/WebCore/bindings/v8/custom/V8EventCustom.cpp b/WebCore/bindings/v8/custom/V8EventCustom.cpp index 79bddc0..b2728ec 100644 --- a/WebCore/bindings/v8/custom/V8EventCustom.cpp +++ b/WebCore/bindings/v8/custom/V8EventCustom.cpp @@ -33,11 +33,13 @@ #include "Clipboard.h" #include "ClipboardEvent.h" +#include "CustomEvent.h" #include "Event.h" #include "V8BeforeLoadEvent.h" #include "V8Binding.h" #include "V8Clipboard.h" #include "V8CompositionEvent.h" +#include "V8CustomEvent.h" #include "V8ErrorEvent.h" #include "V8KeyboardEvent.h" #include "V8MessageEvent.h" @@ -48,7 +50,6 @@ #include "V8PopStateEvent.h" #include "V8ProgressEvent.h" #include "V8Proxy.h" -#include "V8SVGZoomEvent.h" #include "V8StorageEvent.h" #include "V8TextEvent.h" #include "V8TouchEvent.h" @@ -58,6 +59,10 @@ #include "V8WheelEvent.h" #include "V8XMLHttpRequestProgressEvent.h" +#if ENABLE(SVG) +#include "V8SVGZoomEvent.h" +#endif + namespace WebCore { void V8Event::valueAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) @@ -140,6 +145,8 @@ v8::Handle<v8::Value> toV8(Event* impl) #endif if (impl->isBeforeLoadEvent()) return toV8(static_cast<BeforeLoadEvent*>(impl)); + if (impl->isCustomEvent()) + return toV8(static_cast<CustomEvent*>(impl)); return V8Event::wrap(impl); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8EventSourceConstructor.cpp b/WebCore/bindings/v8/custom/V8EventSourceConstructor.cpp index 793ffb6..01e9c44 100644 --- a/WebCore/bindings/v8/custom/V8EventSourceConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8EventSourceConstructor.cpp @@ -56,17 +56,17 @@ v8::Handle<v8::Value> V8EventSource::constructorCallback(const v8::Arguments& ar if (!context) return throwError("EventSource constructor's associated context is not available", V8Proxy::ReferenceError); if (args.Length() != 1) - return throwError("EventSource constructor wrong number of parameters", V8Proxy::TypeError); + return throwError("Not enough arguments", V8Proxy::SyntaxError); ExceptionCode ec = 0; String url = toWebCoreString(args[0]); RefPtr<EventSource> eventSource = EventSource::create(url, context, ec); - + if (ec) return throwError(ec); - V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::EVENTSOURCE), eventSource.get()); + V8DOMWrapper::setDOMWrapper(args.Holder(), &info, eventSource.get()); // Add object to the wrapper map. eventSource->ref(); diff --git a/WebCore/bindings/v8/custom/V8EventSourceCustom.cpp b/WebCore/bindings/v8/custom/V8EventSourceCustom.cpp deleted file mode 100644 index a7f79db..0000000 --- a/WebCore/bindings/v8/custom/V8EventSourceCustom.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2010, The Android Open Source Project - * - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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(EVENTSOURCE) -#include "V8EventSource.h" - -#include "EventSource.h" - -#include "V8Binding.h" -#include "V8Proxy.h" - -namespace WebCore { - -v8::Handle<v8::Value> V8EventSource::addEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.EventSource.addEventListener()"); - EventSource* eventSource = V8EventSource::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(eventSource, args[1], false, ListenerFindOrCreate); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - eventSource->addEventListener(type, listener, useCapture); - - createHiddenDependency(args.Holder(), args[1], cacheIndex); - } - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8EventSource::removeEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.EventSource.removeEventListener()"); - EventSource* eventSource = V8EventSource::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(eventSource, args[1], false, ListenerFindOnly); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - eventSource->removeEventListener(type, listener.get(), useCapture); - - removeHiddenDependency(args.Holder(), args[1], cacheIndex); - } - - return v8::Undefined(); -} - -} // namespace WebCore - -#endif // ENABLE(EVENTSOURCE) diff --git a/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.cpp b/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.cpp index 9b75db8..df16501 100644 --- a/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.cpp @@ -44,6 +44,8 @@ namespace WebCore { +WrapperTypeInfo V8HTMLAudioElementConstructor::info = { V8HTMLAudioElementConstructor::GetTemplate, 0, false }; + static v8::Handle<v8::Value> v8HTMLAudioElementConstructorCallback(const v8::Arguments& args) { INC_STATS("DOM.HTMLAudioElement.Contructor"); @@ -69,7 +71,7 @@ static v8::Handle<v8::Value> v8HTMLAudioElementConstructorCallback(const v8::Arg src = toWebCoreString(args[0]); RefPtr<HTMLAudioElement> audio = HTMLAudioElement::createForJSConstructor(document, src); - V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::AUDIO), audio.get()); + V8DOMWrapper::setDOMWrapper(args.Holder(), &V8HTMLAudioElementConstructor::info, audio.get()); audio->ref(); V8DOMWrapper::setJSWrapperForDOMNode(audio.get(), v8::Persistent<v8::Object>::New(args.Holder())); return args.Holder(); diff --git a/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.h b/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.h index 711f539..8bc5f2c 100755 --- a/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.h +++ b/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.h @@ -31,6 +31,8 @@ #ifndef V8HTMLAudioElementConstructor_h #define V8HTMLAudioElementConstructor_h +#include "WrapperTypeInfo.h" + #include <v8.h> namespace WebCore { @@ -38,6 +40,7 @@ namespace WebCore { class V8HTMLAudioElementConstructor { public: static v8::Persistent<v8::FunctionTemplate> GetTemplate(); + static WrapperTypeInfo info; }; } diff --git a/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp index 54a003c..67ba38b 100644 --- a/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp @@ -39,7 +39,9 @@ #include "V8CanvasRenderingContext2D.h" #include "V8Node.h" #include "V8Proxy.h" +#if ENABLE(3D_CANVAS) #include "V8WebGLRenderingContext.h" +#endif namespace WebCore { @@ -54,7 +56,7 @@ v8::Handle<v8::Value> V8HTMLCanvasElement::getContextCallback(const v8::Argument if (contextId == "experimental-webgl" || contextId == "webkit-3d") { attrs = WebGLContextAttributes::create(); WebGLContextAttributes* webGLAttrs = static_cast<WebGLContextAttributes*>(attrs.get()); - if (args.Length() > 1 && args[0]->IsObject()) { + if (args.Length() > 1 && args[1]->IsObject()) { v8::Handle<v8::Object> jsAttrs = args[1]->ToObject(); v8::Handle<v8::String> alpha = v8::String::New("alpha"); if (jsAttrs->Has(alpha)) diff --git a/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp b/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp index 29b4813..4751224 100644 --- a/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp @@ -44,6 +44,8 @@ namespace WebCore { +WrapperTypeInfo V8HTMLImageElementConstructor::info = { V8HTMLImageElementConstructor::GetTemplate, 0, false }; + static v8::Handle<v8::Value> v8HTMLImageElementConstructorCallback(const v8::Arguments& args) { INC_STATS("DOM.HTMLImageElement.Contructor"); @@ -80,7 +82,7 @@ static v8::Handle<v8::Value> v8HTMLImageElementConstructorCallback(const v8::Arg } RefPtr<HTMLImageElement> image = HTMLImageElement::createForJSConstructor(document, optionalWidth, optionalHeight); - V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::IMAGE), image.get()); + V8DOMWrapper::setDOMWrapper(args.Holder(), &V8HTMLImageElementConstructor::info, image.get()); image->ref(); V8DOMWrapper::setJSWrapperForDOMNode(image.get(), v8::Persistent<v8::Object>::New(args.Holder())); return args.Holder(); diff --git a/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.h b/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.h index 19ee944..5db4946 100755 --- a/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.h +++ b/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.h @@ -31,6 +31,8 @@ #ifndef V8HTMLImageElementConstructor_h #define V8HTMLImageElementConstructor_h +#include "WrapperTypeInfo.h" + #include <v8.h> namespace WebCore { @@ -38,6 +40,7 @@ namespace WebCore { class V8HTMLImageElementConstructor { public: static v8::Persistent<v8::FunctionTemplate> GetTemplate(); + static WrapperTypeInfo info; }; } diff --git a/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp b/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp index 1ff1d2e..6b84856 100644 --- a/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp @@ -44,6 +44,8 @@ namespace WebCore { +WrapperTypeInfo V8HTMLOptionElementConstructor::info = { V8HTMLOptionElementConstructor::GetTemplate, 0, false }; + static v8::Handle<v8::Value> v8HTMLOptionElementConstructorCallback(const v8::Arguments& args) { INC_STATS("DOM.HTMLOptionElement.Contructor"); @@ -78,7 +80,7 @@ static v8::Handle<v8::Value> v8HTMLOptionElementConstructorCallback(const v8::Ar if (ec) throwError(ec); - V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::OPTION), option.get()); + V8DOMWrapper::setDOMWrapper(args.Holder(), &V8HTMLOptionElementConstructor::info, option.get()); option->ref(); V8DOMWrapper::setJSWrapperForDOMNode(option.get(), v8::Persistent<v8::Object>::New(args.Holder())); return args.Holder(); diff --git a/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.h b/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.h index 905a745..2adf0fe 100755 --- a/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.h +++ b/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.h @@ -31,6 +31,8 @@ #ifndef V8HTMLOptionElementConstructor_h #define V8HTMLOptionElementConstructor_h +#include "WrapperTypeInfo.h" + #include <v8.h> namespace WebCore { @@ -38,6 +40,7 @@ namespace WebCore { class V8HTMLOptionElementConstructor { public: static v8::Persistent<v8::FunctionTemplate> GetTemplate(); + static WrapperTypeInfo info; }; } diff --git a/WebCore/bindings/v8/custom/V8HistoryCustom.cpp b/WebCore/bindings/v8/custom/V8HistoryCustom.cpp index 6075ec5..ad2b9a9 100644 --- a/WebCore/bindings/v8/custom/V8HistoryCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HistoryCustom.cpp @@ -43,7 +43,10 @@ namespace WebCore { v8::Handle<v8::Value> V8History::pushStateCallback(const v8::Arguments& args) { - RefPtr<SerializedScriptValue> historyState = SerializedScriptValue::create(args[0]); + bool didThrow = false; + RefPtr<SerializedScriptValue> historyState = SerializedScriptValue::create(args[0], didThrow); + if (didThrow) + return v8::Undefined(); v8::TryCatch tryCatch; String title = toWebCoreStringWithNullOrUndefinedCheck(args[1]); @@ -64,7 +67,10 @@ v8::Handle<v8::Value> V8History::pushStateCallback(const v8::Arguments& args) v8::Handle<v8::Value> V8History::replaceStateCallback(const v8::Arguments& args) { - RefPtr<SerializedScriptValue> historyState = SerializedScriptValue::create(args[0]); + bool didThrow = false; + RefPtr<SerializedScriptValue> historyState = SerializedScriptValue::create(args[0], didThrow); + if (didThrow) + return v8::Undefined(); v8::TryCatch tryCatch; String title = toWebCoreStringWithNullOrUndefinedCheck(args[1]); @@ -83,33 +89,18 @@ v8::Handle<v8::Value> V8History::replaceStateCallback(const v8::Arguments& args) return throwError(ec); } -bool V8History::indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType type, v8::Local<v8::Value> data) +bool V8History::indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType type, v8::Local<v8::Value>) { - ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::HISTORY); // Only allow same origin access. History* history = V8History::toNative(host); return V8BindingSecurity::canAccessFrame(V8BindingState::Only(), history->frame(), false); } -bool V8History::namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value> data) +bool V8History::namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value>) { - ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::HISTORY); // Only allow same origin access. History* history = V8History::toNative(host); return V8BindingSecurity::canAccessFrame(V8BindingState::Only(), history->frame(), false); } -v8::Handle<v8::Value> toV8(History* impl) -{ - if (!impl) - return v8::Null(); - v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(impl); - if (wrapper.IsEmpty()) { - wrapper = V8History::wrap(impl); - if (!wrapper.IsEmpty()) - V8DOMWrapper::setHiddenWindowReference(impl->frame(), V8DOMWindow::historyIndex, wrapper); - } - return wrapper; -} - } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8IndexedDatabaseRequestCustom.cpp b/WebCore/bindings/v8/custom/V8IndexedDatabaseRequestCustom.cpp index 0fd182c..e8c2b68 100644 --- a/WebCore/bindings/v8/custom/V8IndexedDatabaseRequestCustom.cpp +++ b/WebCore/bindings/v8/custom/V8IndexedDatabaseRequestCustom.cpp @@ -33,7 +33,12 @@ #if ENABLE(INDEXED_DATABASE) #include "V8IndexedDatabaseRequest.h" +#include "IDBDatabaseError.h" +#include "IDBDatabaseRequest.h" #include "V8Binding.h" +#include "V8CustomIDBCallbacks.h" +#include "V8IDBDatabaseError.h" +#include "V8IDBDatabaseRequest.h" #include "V8Proxy.h" namespace WebCore { @@ -45,12 +50,32 @@ v8::Handle<v8::Value> V8IndexedDatabaseRequest::openCallback(const v8::Arguments return throwError(V8Proxy::TypeError); V8Parameter<> name = args[0]; V8Parameter<> description = args[1]; + bool modifyDatabase = true; - if (args.Length() > 2) + if (args.Length() > 2 && !args[2]->IsUndefined() && !args[2]->IsNull()) modifyDatabase = args[2]->BooleanValue(); + v8::Local<v8::Value> onError; + v8::Local<v8::Value> onSuccess; + if (args.Length() > 3 && !args[3]->IsUndefined() && !args[3]->IsNull()) { + if (!args[3]->IsObject()) + return throwError("onerror callback was not the proper type"); + onError = args[3]; + } + if (args.Length() > 4 && !args[4]->IsUndefined() && !args[4]->IsNull()) { + if (!args[4]->IsObject()) + return throwError("onsuccess callback was not the proper type"); + onSuccess = args[4]; + } + if (!onError->IsObject() && !onSuccess->IsObject()) + return throwError("Neither the onerror nor the onsuccess callbacks were set."); + + Frame* frame = V8Proxy::retrieveFrameForCurrentContext(); + RefPtr<V8CustomIDBCallbacks<IDBDatabase, IDBDatabaseRequest> > callbacks = + V8CustomIDBCallbacks<IDBDatabase, IDBDatabaseRequest>::create(onSuccess, onError, frame->document()); + ExceptionCode ec = 0; - imp->open(name, description, modifyDatabase, ec); + imp->open(name, description, modifyDatabase, callbacks, ec); if (ec) return throwError(ec); return v8::Handle<v8::Value>(); diff --git a/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp b/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp index 054f9ba..4c091c8 100644 --- a/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp +++ b/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp @@ -39,10 +39,14 @@ #include "InspectorController.h" #include "Node.h" #include "Page.h" +#include "ScriptDebugServer.h" #include "SerializedScriptValue.h" #include "V8Binding.h" +#include "V8BindingState.h" +#include "V8DOMWindow.h" #include "V8Database.h" +#include "V8JavaScriptCallFrame.h" #include "V8Node.h" #include "V8Proxy.h" #include "V8Storage.h" @@ -59,7 +63,6 @@ static void WeakReferenceCallback(v8::Persistent<v8::Value> object, void* parame static v8::Local<v8::Object> createInjectedScriptHostV8Wrapper(InjectedScriptHost* host) { - V8ClassIndex::V8WrapperType descriptorType = V8ClassIndex::INJECTEDSCRIPTHOST; v8::Local<v8::Function> function = V8InjectedScriptHost::GetTemplate()->GetFunction(); if (function.IsEmpty()) { // Return if allocation failed. @@ -70,7 +73,7 @@ static v8::Local<v8::Object> createInjectedScriptHostV8Wrapper(InjectedScriptHos // Avoid setting the wrapper if allocation failed. return v8::Local<v8::Object>(); } - V8DOMWrapper::setDOMWrapper(instance, V8ClassIndex::ToInt(descriptorType), host); + V8DOMWrapper::setDOMWrapper(instance, &V8InjectedScriptHost::info, host); // Create a weak reference to the v8 wrapper of InspectorBackend to deref // InspectorBackend when the wrapper is garbage collected. host->ref(); @@ -79,7 +82,7 @@ static v8::Local<v8::Object> createInjectedScriptHostV8Wrapper(InjectedScriptHos return instance; } -static ScriptObject createInjectedScript(const String& scriptSource, InjectedScriptHost* injectedScriptHost, ScriptState* inspectedScriptState, long id) +ScriptObject InjectedScriptHost::createInjectedScript(const String& scriptSource, ScriptState* inspectedScriptState, long id) { v8::HandleScope scope; @@ -90,7 +93,7 @@ static ScriptObject createInjectedScript(const String& scriptSource, InjectedScr // instead of calling toV8() that would create the // wrapper in the current context. // FIXME: make it possible to use generic bindings factory for InjectedScriptHost. - v8::Local<v8::Object> scriptHostWrapper = createInjectedScriptHostV8Wrapper(injectedScriptHost); + v8::Local<v8::Object> scriptHostWrapper = createInjectedScriptHostV8Wrapper(this); if (scriptHostWrapper.IsEmpty()) return ScriptObject(); @@ -109,9 +112,10 @@ static ScriptObject createInjectedScript(const String& scriptSource, InjectedScr v8::Handle<v8::Value> args[] = { scriptHostWrapper, windowGlobal, - v8::Number::New(id) + v8::Number::New(id), + v8::String::New("v8") }; - v8::Local<v8::Value> injectedScriptValue = v8::Function::Cast(*v)->Call(windowGlobal, 3, args); + v8::Local<v8::Value> injectedScriptValue = v8::Function::Cast(*v)->Call(windowGlobal, 4, args); v8::Local<v8::Object> injectedScript(v8::Object::Cast(*injectedScriptValue)); return ScriptObject(inspectedScriptState, injectedScript); } @@ -151,6 +155,20 @@ v8::Handle<v8::Value> V8InjectedScriptHost::pushNodePathToFrontendCallback(const return v8::Undefined(); } +#if ENABLE(JAVASCRIPT_DEBUGGER) +v8::Handle<v8::Value> V8InjectedScriptHost::currentCallFrameCallback(const v8::Arguments& args) +{ + INC_STATS("InjectedScriptHost.currentCallFrame()"); + return toV8(ScriptDebugServer::shared().currentCallFrame()); +} + +v8::Handle<v8::Value> V8InjectedScriptHost::isActivationCallback(const v8::Arguments& args) +{ + INC_STATS("InjectedScriptHost.isActivation()"); + return v8::Boolean::New(true); +} +#endif + #if ENABLE(DATABASE) v8::Handle<v8::Value> V8InjectedScriptHost::databaseForIdCallback(const v8::Arguments& args) { @@ -226,12 +244,27 @@ InjectedScript InjectedScriptHost::injectedScriptFor(ScriptState* inspectedScrip return InjectedScript(ScriptObject(inspectedScriptState, v8::Local<v8::Object>::Cast(val))); ASSERT(!m_injectedScriptSource.isEmpty()); - ScriptObject injectedScriptObject = createInjectedScript(m_injectedScriptSource, this, inspectedScriptState, m_nextInjectedScriptId); - InjectedScript result(injectedScriptObject); - m_idToInjectedScript.set(m_nextInjectedScriptId, result); - ++m_nextInjectedScriptId; - global->SetHiddenValue(key, injectedScriptObject.v8Object()); + pair<long, ScriptObject> injectedScript = injectScript(m_injectedScriptSource, inspectedScriptState); + InjectedScript result(injectedScript.second); + m_idToInjectedScript.set(injectedScript.first, result); + global->SetHiddenValue(key, injectedScript.second.v8Object()); return result; } +bool InjectedScriptHost::canAccessInspectedWindow(ScriptState* scriptState) +{ + v8::HandleScope handleScope; + v8::Local<v8::Context> context = scriptState->context(); + v8::Local<v8::Object> global = context->Global(); + if (global.IsEmpty()) + return false; + v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), global); + if (holder.IsEmpty()) + return false; + Frame* frame = V8DOMWindow::toNative(holder)->frame(); + + v8::Context::Scope contextScope(context); + return V8BindingSecurity::canAccessFrame(V8BindingState::Only(), frame, false); +} + } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8InspectorFrontendHostCustom.cpp b/WebCore/bindings/v8/custom/V8InspectorFrontendHostCustom.cpp index b823034..7f4ccf7 100644 --- a/WebCore/bindings/v8/custom/V8InspectorFrontendHostCustom.cpp +++ b/WebCore/bindings/v8/custom/V8InspectorFrontendHostCustom.cpp @@ -35,12 +35,65 @@ #include "InspectorFrontendHost.h" #include "V8Binding.h" +#include "V8MouseEvent.h" #include "V8Proxy.h" namespace WebCore { +v8::Handle<v8::Value> V8InspectorFrontendHost::platformCallback(const v8::Arguments&) +{ +#if defined(OS_MACOSX) + return v8String("mac"); +#elif defined(OS_LINUX) + return v8String("linux"); +#elif defined(OS_WIN) + return v8String("windows"); +#else + return v8String("unknown"); +#endif +} + +v8::Handle<v8::Value> V8InspectorFrontendHost::portCallback(const v8::Arguments&) +{ + return v8::Undefined(); +} + v8::Handle<v8::Value> V8InspectorFrontendHost::showContextMenuCallback(const v8::Arguments& args) { + if (args.Length() < 2) + return v8::Undefined(); + + v8::Local<v8::Object> eventWrapper = v8::Local<v8::Object>::Cast(args[0]); + if (!V8MouseEvent::info.equals(V8DOMWrapper::domWrapperType(eventWrapper))) + return v8::Undefined(); + + Event* event = V8Event::toNative(eventWrapper); + if (!args[1]->IsArray()) + return v8::Undefined(); + + v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(args[1]); + Vector<ContextMenuItem*> items; + + for (size_t i = 0; i < array->Length(); ++i) { + v8::Local<v8::Object> item = v8::Local<v8::Object>::Cast(array->Get(v8::Integer::New(i))); + v8::Local<v8::Value> label = item->Get(v8::String::New("label")); + v8::Local<v8::Value> id = item->Get(v8::String::New("id")); + if (label->IsUndefined() || id->IsUndefined()) { + items.append(new ContextMenuItem(SeparatorType, + ContextMenuItemTagNoAction, + String())); + } else { + ContextMenuAction typedId = static_cast<ContextMenuAction>( + ContextMenuItemBaseCustomTag + id->ToInt32()->Value()); + items.append(new ContextMenuItem(ActionType, + typedId, + toWebCoreStringWithNullCheck(label))); + } + } + + InspectorFrontendHost* frontendHost = V8InspectorFrontendHost::toNative(args.Holder()); + frontendHost->showContextMenu(event, items); + return v8::Undefined(); } diff --git a/WebCore/bindings/v8/custom/V8JavaScriptCallFrameCustom.cpp b/WebCore/bindings/v8/custom/V8JavaScriptCallFrameCustom.cpp new file mode 100644 index 0000000..e2a691d --- /dev/null +++ b/WebCore/bindings/v8/custom/V8JavaScriptCallFrameCustom.cpp @@ -0,0 +1,79 @@ +/* + * 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 "V8JavaScriptCallFrame.h" + +#if ENABLE(JAVASCRIPT_DEBUGGER) + +#include "V8Binding.h" +#include "V8Proxy.h" + +namespace WebCore { + +v8::Handle<v8::Value> V8JavaScriptCallFrame::evaluateCallback(const v8::Arguments& args) +{ + INC_STATS("V8JavaScriptCallFrame.evaluateCallback()"); + JavaScriptCallFrame* impl = V8JavaScriptCallFrame::toNative(args.Holder()); + String expression = toWebCoreStringWithNullOrUndefinedCheck(args[0]); + return impl->evaluate(expression); +} + +v8::Handle<v8::Value> V8JavaScriptCallFrame::scopeChainAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("V8JavaScriptCallFrame.scopeChainAccessorGetter()"); + JavaScriptCallFrame* impl = V8JavaScriptCallFrame::toNative(info.Holder()); + return impl->scopeChain(); +} + +v8::Handle<v8::Value> V8JavaScriptCallFrame::scopeTypeCallback(const v8::Arguments& args) +{ + INC_STATS("V8JavaScriptCallFrame.scopeTypeCallback()"); + JavaScriptCallFrame* impl = V8JavaScriptCallFrame::toNative(args.Holder()); + int scopeIndex = args[0]->Int32Value(); + return v8::Int32::New(impl->scopeType(scopeIndex)); +} + +v8::Handle<v8::Value> V8JavaScriptCallFrame::thisObjectAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("V8JavaScriptCallFrame.thisObjectAccessorGetter()"); + JavaScriptCallFrame* impl = V8JavaScriptCallFrame::toNative(info.Holder()); + return impl->thisObject(); +} + +v8::Handle<v8::Value> V8JavaScriptCallFrame::typeAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("V8JavaScriptCallFrame.typeAccessorGetter()"); + return v8String("function"); +} + +} // namespace WebCore + +#endif // ENABLE(JAVASCRIPT_DEBUGGER) diff --git a/WebCore/bindings/v8/custom/V8LocationCustom.cpp b/WebCore/bindings/v8/custom/V8LocationCustom.cpp index b5df601..ac305c9 100644 --- a/WebCore/bindings/v8/custom/V8LocationCustom.cpp +++ b/WebCore/bindings/v8/custom/V8LocationCustom.cpp @@ -75,9 +75,14 @@ void V8Location::hashAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Va if (hash.startsWith("#")) hash = hash.substring(1); - if (oldRef == hash || (oldRef.isNull() && hash.isEmpty())) - return; + + // Note that by parsing the URL and *then* comparing fragments, we are + // comparing fragments post-canonicalization, and so this handles the + // cases where fragment identifiers are ignored or invalid. url.setFragmentIdentifier(hash); + String newRef = url.fragmentIdentifier(); + if (oldRef == newRef || (oldRef.isNull() && newRef.isEmpty())) + return; navigateIfAllowed(frame, url, false, false); } @@ -185,7 +190,10 @@ void V8Location::protocolAccessorSetter(v8::Local<v8::String> name, v8::Local<v8 return; KURL url = frame->loader()->url(); - url.setProtocol(protocol); + if (!url.setProtocol(protocol)) { + throwError("Can't set protocol", V8Proxy::SyntaxError); + return; + } navigateIfAllowed(frame, url, false, false); } @@ -342,17 +350,15 @@ v8::Handle<v8::Value> V8Location::toStringCallback(const v8::Arguments& args) return v8String(result); } -bool V8Location::indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType type, v8::Local<v8::Value> data) +bool V8Location::indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType type, v8::Local<v8::Value>) { - ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::LOCATION); // Only allow same origin access Location* imp = V8Location::toNative(host); return V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false); } -bool V8Location::namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value> data) +bool V8Location::namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value>) { - ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::LOCATION); // Only allow same origin access Location* imp = V8Location::toNative(host); return V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false); @@ -366,7 +372,7 @@ v8::Handle<v8::Value> toV8(Location* impl) if (wrapper.IsEmpty()) { wrapper = V8Location::wrap(impl); if (!wrapper.IsEmpty()) - V8DOMWrapper::setHiddenWindowReference(impl->frame(), V8DOMWindow::locationIndex, wrapper); + V8DOMWrapper::setHiddenWindowReference(impl->frame(), wrapper); } return wrapper; } diff --git a/WebCore/bindings/v8/custom/V8MessageChannelConstructor.cpp b/WebCore/bindings/v8/custom/V8MessageChannelConstructor.cpp index 4fb82ba..b966e42 100644 --- a/WebCore/bindings/v8/custom/V8MessageChannelConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8MessageChannelConstructor.cpp @@ -67,11 +67,11 @@ v8::Handle<v8::Value> V8MessageChannel::constructorCallback(const v8::Arguments& // Create references from the MessageChannel wrapper to the two // MessagePort wrappers to make sure that the MessagePort wrappers // stay alive as long as the MessageChannel wrapper is around. - messageChannel->SetInternalField(V8MessageChannel::port1Index, toV8(obj->port1())); - messageChannel->SetInternalField(V8MessageChannel::port2Index, toV8(obj->port2())); + V8DOMWrapper::setHiddenReference(messageChannel, toV8(obj->port1())); + V8DOMWrapper::setHiddenReference(messageChannel, toV8(obj->port2())); // Setup the standard wrapper object internal fields. - V8DOMWrapper::setDOMWrapper(messageChannel, V8ClassIndex::MESSAGECHANNEL, obj.get()); + V8DOMWrapper::setDOMWrapper(messageChannel, &info, obj.get()); return toV8(obj.release(), messageChannel); } diff --git a/WebCore/bindings/v8/custom/V8MessageEventCustom.cpp b/WebCore/bindings/v8/custom/V8MessageEventCustom.cpp index d41a785..cca4a24 100644 --- a/WebCore/bindings/v8/custom/V8MessageEventCustom.cpp +++ b/WebCore/bindings/v8/custom/V8MessageEventCustom.cpp @@ -84,6 +84,8 @@ v8::Handle<v8::Value> V8MessageEvent::initMessageEventCallback(const v8::Argumen return v8::Undefined(); } event->initMessageEvent(typeArg, canBubbleArg, cancelableArg, dataArg.release(), originArg, lastEventIdArg, sourceArg, portArray.release()); + v8::PropertyAttribute dataAttr = static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly); + SerializedScriptValue::deserializeAndSetProperty(args.Holder(), "data", dataAttr, event->data()); return v8::Undefined(); } diff --git a/WebCore/bindings/v8/custom/V8MessagePortCustom.cpp b/WebCore/bindings/v8/custom/V8MessagePortCustom.cpp index 9890668..c41ed38 100644 --- a/WebCore/bindings/v8/custom/V8MessagePortCustom.cpp +++ b/WebCore/bindings/v8/custom/V8MessagePortCustom.cpp @@ -42,42 +42,14 @@ namespace WebCore { -v8::Handle<v8::Value> V8MessagePort::addEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.MessagePort.addEventListener()"); - MessagePort* messagePort = V8MessagePort::toNative(args.Holder()); - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(messagePort, args[1], false, ListenerFindOrCreate); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - messagePort->addEventListener(type, listener, useCapture); - - createHiddenDependency(args.Holder(), args[1], cacheIndex); - } - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8MessagePort::removeEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.MessagePort.removeEventListener()"); - MessagePort* messagePort = V8MessagePort::toNative(args.Holder()); - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(messagePort, args[1], false, ListenerFindOnly); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - messagePort->removeEventListener(type, listener.get(), useCapture); - - removeHiddenDependency(args.Holder(), args[1], cacheIndex); - } - - return v8::Undefined(); -} - v8::Handle<v8::Value> V8MessagePort::postMessageCallback(const v8::Arguments& args) { INC_STATS("DOM.MessagePort.postMessage"); MessagePort* messagePort = V8MessagePort::toNative(args.Holder()); - RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(args[0]); + bool didThrow = false; + RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(args[0], didThrow); + if (didThrow) + return v8::Undefined(); MessagePortArray portArray; if (args.Length() > 1) { if (!getMessagePortArray(args[1], portArray)) diff --git a/WebCore/bindings/v8/custom/V8NamedNodeMapCustom.cpp b/WebCore/bindings/v8/custom/V8NamedNodeMapCustom.cpp index 611ab94..4e1dd21 100644 --- a/WebCore/bindings/v8/custom/V8NamedNodeMapCustom.cpp +++ b/WebCore/bindings/v8/custom/V8NamedNodeMapCustom.cpp @@ -32,7 +32,9 @@ #include "V8NamedNodeMap.h" #include "NamedNodeMap.h" +#include "V8Attr.h" #include "V8Binding.h" +#include "V8BindingState.h" #include "V8Element.h" #include "V8Node.h" #include "V8Proxy.h" @@ -73,6 +75,48 @@ v8::Handle<v8::Value> V8NamedNodeMap::namedPropertyGetter(v8::Local<v8::String> return toV8(result.release()); } +v8::Handle<v8::Value> V8NamedNodeMap::setNamedItemNSCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.NamedNodeMap.setNamedItemNS"); + NamedNodeMap* imp = V8NamedNodeMap::toNative(args.Holder()); + Node* newNode = V8Node::HasInstance(args[0]) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; + + if (newNode && newNode->nodeType() == Node::ATTRIBUTE_NODE && imp->element()) { + if (!V8BindingSecurity::allowSettingSrcToJavascriptURL(V8BindingState::Only(), imp->element(), newNode->nodeName(), newNode->nodeValue())) + return v8::Handle<v8::Value>(); + } + + ExceptionCode ec = 0; + RefPtr<Node> result = imp->setNamedItemNS(newNode, ec); + if (UNLIKELY(ec)) { + throwError(ec); + return v8::Handle<v8::Value>(); + } + + return toV8(result.release()); +} + +v8::Handle<v8::Value> V8NamedNodeMap::setNamedItemCallback(const v8::Arguments & args) +{ + INC_STATS("DOM.NamedNodeMap.setNamedItem"); + NamedNodeMap* imp = V8NamedNodeMap::toNative(args.Holder()); + Node* newNode = V8Node::HasInstance(args[0]) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; + + if (newNode && newNode->nodeType() == Node::ATTRIBUTE_NODE && imp->element()) { + if (!V8BindingSecurity::allowSettingSrcToJavascriptURL(V8BindingState::Only(), imp->element(), newNode->nodeName(), newNode->nodeValue())) + return v8::Handle<v8::Value>(); + } + + ExceptionCode ec = 0; + RefPtr<Node> result = imp->setNamedItem(newNode, ec); + if (UNLIKELY(ec)) { + throwError(ec); + return v8::Handle<v8::Value>(); + } + + return toV8(result.release()); +} + v8::Handle<v8::Value> toV8(NamedNodeMap* impl) { if (!impl) @@ -80,10 +124,8 @@ v8::Handle<v8::Value> toV8(NamedNodeMap* impl) v8::Handle<v8::Object> wrapper = V8NamedNodeMap::wrap(impl); // Add a hidden reference from named node map to its owner node. Element* element = impl->element(); - if (!wrapper.IsEmpty() && element) { - v8::Handle<v8::Value> owner = toV8(element); - wrapper->SetInternalField(V8NamedNodeMap::ownerNodeIndex, owner); - } + if (!wrapper.IsEmpty() && element) + V8DOMWrapper::setHiddenReference(wrapper, toV8(element)); return wrapper; } diff --git a/WebCore/bindings/v8/custom/V8NodeCustom.cpp b/WebCore/bindings/v8/custom/V8NodeCustom.cpp index 7907283..0a7198a 100644 --- a/WebCore/bindings/v8/custom/V8NodeCustom.cpp +++ b/WebCore/bindings/v8/custom/V8NodeCustom.cpp @@ -37,6 +37,7 @@ #include "V8AbstractEventListener.h" #include "V8Attr.h" #include "V8Binding.h" +#include "V8BindingState.h" #include "V8CDATASection.h" #include "V8Comment.h" #include "V8CustomEventListener.h" @@ -56,38 +57,43 @@ namespace WebCore { -v8::Handle<v8::Value> V8Node::addEventListenerCallback(const v8::Arguments& args) +static inline bool isFrameSrc(Element *element, const String& name) { - INC_STATS("DOM.Node.addEventListener()"); - Node* node = V8Node::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(node, args[1], false, ListenerFindOrCreate); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - node->addEventListener(type, listener, useCapture); - createHiddenDependency(args.Holder(), args[1], cacheIndex); + return element && (element->hasTagName(HTMLNames::iframeTag) || element->hasTagName(HTMLNames::frameTag)) && equalIgnoringCase(name, "src"); +} + +void V8Node::textContentAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) +{ + Node* imp = V8Node::toNative(info.Holder()); + String nodeValue = toWebCoreStringWithNullCheck(value); + + if (imp->nodeType() == Node::ATTRIBUTE_NODE) { + Element * ownerElement = V8Attr::toNative(info.Holder())->ownerElement(); + if (ownerElement && !V8BindingSecurity::allowSettingSrcToJavascriptURL(V8BindingState::Only(), ownerElement, imp->nodeName(), nodeValue)) + return; } - return v8::Undefined(); + + ExceptionCode ec = 0; + imp->setTextContent(nodeValue, ec); + if (ec) + throwError(ec); } -v8::Handle<v8::Value> V8Node::removeEventListenerCallback(const v8::Arguments& args) +void V8Node::nodeValueAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { - INC_STATS("DOM.Node.removeEventListener()"); - Node* node = V8Node::toNative(args.Holder()); - - // It is possbile that the owner document of the node is detached - // from the frame. - // See issue http://b/878909 - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(node, args[1], false, ListenerFindOnly); - if (listener) { - AtomicString type = v8ValueToAtomicWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - node->removeEventListener(type, listener.get(), useCapture); - removeHiddenDependency(args.Holder(), args[1], cacheIndex); + Node* imp = V8Node::toNative(info.Holder()); + String nodeValue = toWebCoreStringWithNullCheck(value); + + if (imp->nodeType() == Node::ATTRIBUTE_NODE) { + Element * ownerElement = V8Attr::toNative(info.Holder())->ownerElement(); + if (ownerElement && !V8BindingSecurity::allowSettingSrcToJavascriptURL(V8BindingState::Only(), ownerElement, imp->nodeName(), nodeValue)) + return; } - return v8::Undefined(); + ExceptionCode ec = 0; + imp->setNodeValue(nodeValue, ec); + if (ec) + throwError(ec); } // This function is customized to take advantage of the optional 4th argument: shouldLazyAttach @@ -96,6 +102,12 @@ v8::Handle<v8::Value> V8Node::insertBeforeCallback(const v8::Arguments& args) INC_STATS("DOM.Node.insertBefore"); v8::Handle<v8::Object> holder = args.Holder(); Node* imp = V8Node::toNative(holder); + + if (imp->nodeType() == Node::ATTRIBUTE_NODE && isFrameSrc(V8Attr::toNative(holder)->ownerElement(), imp->nodeName())) { + V8Proxy::setDOMException(NOT_SUPPORTED_ERR); + return v8::Handle<v8::Value>(); + } + ExceptionCode ec = 0; Node* newChild = V8Node::HasInstance(args[0]) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; Node* refChild = V8Node::HasInstance(args[1]) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(args[1])) : 0; @@ -115,6 +127,12 @@ v8::Handle<v8::Value> V8Node::replaceChildCallback(const v8::Arguments& args) INC_STATS("DOM.Node.replaceChild"); v8::Handle<v8::Object> holder = args.Holder(); Node* imp = V8Node::toNative(holder); + + if (imp->nodeType() == Node::ATTRIBUTE_NODE && isFrameSrc(V8Attr::toNative(holder)->ownerElement(), imp->nodeName())) { + V8Proxy::setDOMException(NOT_SUPPORTED_ERR); + return v8::Handle<v8::Value>(); + } + ExceptionCode ec = 0; Node* newChild = V8Node::HasInstance(args[0]) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; Node* oldChild = V8Node::HasInstance(args[1]) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(args[1])) : 0; @@ -133,6 +151,12 @@ v8::Handle<v8::Value> V8Node::removeChildCallback(const v8::Arguments& args) INC_STATS("DOM.Node.removeChild"); v8::Handle<v8::Object> holder = args.Holder(); Node* imp = V8Node::toNative(holder); + + if (imp->nodeType() == Node::ATTRIBUTE_NODE && isFrameSrc(V8Attr::toNative(holder)->ownerElement(), imp->nodeName())) { + V8Proxy::setDOMException(NOT_SUPPORTED_ERR); + return v8::Handle<v8::Value>(); + } + ExceptionCode ec = 0; Node* oldChild = V8Node::HasInstance(args[0]) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; bool success = imp->removeChild(oldChild, ec); @@ -151,6 +175,12 @@ v8::Handle<v8::Value> V8Node::appendChildCallback(const v8::Arguments& args) INC_STATS("DOM.Node.appendChild"); v8::Handle<v8::Object> holder = args.Holder(); Node* imp = V8Node::toNative(holder); + + if (imp->nodeType() == Node::ATTRIBUTE_NODE && isFrameSrc(V8Attr::toNative(holder)->ownerElement(), imp->nodeName())) { + V8Proxy::setDOMException(NOT_SUPPORTED_ERR); + return v8::Handle<v8::Value>(); + } + ExceptionCode ec = 0; Node* newChild = V8Node::HasInstance(args[0]) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; bool success = imp->appendChild(newChild, ec, true ); diff --git a/WebCore/bindings/v8/custom/V8NotificationCenterCustom.cpp b/WebCore/bindings/v8/custom/V8NotificationCenterCustom.cpp index 9c3ab45..30773e3 100644 --- a/WebCore/bindings/v8/custom/V8NotificationCenterCustom.cpp +++ b/WebCore/bindings/v8/custom/V8NotificationCenterCustom.cpp @@ -46,38 +46,6 @@ namespace WebCore { -v8::Handle<v8::Value> V8Notification::addEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.Notification.addEventListener()"); - Notification* notification = V8Notification::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(notification, args[1], false, ListenerFindOrCreate); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - notification->addEventListener(type, listener, useCapture); - createHiddenDependency(args.Holder(), args[1], cacheIndex); - } - - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8Notification::removeEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.Notification.removeEventListener()"); - Notification* notification = V8Notification::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(notification, args[1], false, ListenerFindOnly); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - notification->removeEventListener(type, listener.get(), useCapture); - removeHiddenDependency(args.Holder(), args[1], cacheIndex); - } - - return v8::Undefined(); -} - v8::Handle<v8::Value> V8NotificationCenter::createHTMLNotificationCallback(const v8::Arguments& args) { INC_STATS(L"DOM.NotificationCenter.CreateHTMLNotification()"); diff --git a/WebCore/bindings/v8/custom/V8PopStateEventCustom.cpp b/WebCore/bindings/v8/custom/V8PopStateEventCustom.cpp index 46e9929..cdb160d 100644 --- a/WebCore/bindings/v8/custom/V8PopStateEventCustom.cpp +++ b/WebCore/bindings/v8/custom/V8PopStateEventCustom.cpp @@ -35,6 +35,8 @@ #include "SerializedScriptValue.h" #include "V8Proxy.h" +#include <v8.h> + namespace WebCore { v8::Handle<v8::Value> V8PopStateEvent::initPopStateEventCallback(const v8::Arguments& args) @@ -44,7 +46,11 @@ v8::Handle<v8::Value> V8PopStateEvent::initPopStateEventCallback(const v8::Argum String typeArg = v8ValueToWebCoreString(args[0]); bool canBubbleArg = args[1]->BooleanValue(); bool cancelableArg = args[2]->BooleanValue(); - RefPtr<SerializedScriptValue> stateArg = SerializedScriptValue::create(args[3]); + + bool didThrow = false; + RefPtr<SerializedScriptValue> stateArg = SerializedScriptValue::create(args[3], didThrow); + if (didThrow) + return v8::Undefined(); PopStateEvent* event = V8PopStateEvent::toNative(args.Holder()); event->initPopStateEvent(typeArg, canBubbleArg, cancelableArg, stateArg.release()); diff --git a/WebCore/bindings/v8/custom/V8SVGDocumentCustom.cpp b/WebCore/bindings/v8/custom/V8SVGDocumentCustom.cpp index 558c03b..8dce61b 100644 --- a/WebCore/bindings/v8/custom/V8SVGDocumentCustom.cpp +++ b/WebCore/bindings/v8/custom/V8SVGDocumentCustom.cpp @@ -29,6 +29,8 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "V8SVGDocument.h" #include "V8IsolatedContext.h" @@ -51,3 +53,5 @@ v8::Handle<v8::Value> toV8(SVGDocument* impl, bool forceNewObject) } } // namespace WebCore + +#endif diff --git a/WebCore/bindings/v8/custom/V8SVGElementCustom.cpp b/WebCore/bindings/v8/custom/V8SVGElementCustom.cpp index 0ce48ce..7ad5f41 100644 --- a/WebCore/bindings/v8/custom/V8SVGElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8SVGElementCustom.cpp @@ -29,10 +29,10 @@ */ #include "config.h" -#include "V8SVGElement.h" #if ENABLE(SVG) +#include "V8SVGElement.h" #include "V8SVGElementWrapperFactory.h" namespace WebCore { diff --git a/WebCore/bindings/v8/custom/V8SVGElementInstanceCustom.cpp b/WebCore/bindings/v8/custom/V8SVGElementInstanceCustom.cpp deleted file mode 100644 index 56c37bd..0000000 --- a/WebCore/bindings/v8/custom/V8SVGElementInstanceCustom.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2009 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(SVG) -#include "V8SVGElementInstance.h" - -#include "EventListener.h" -#include "SVGElementInstance.h" - -#include "V8Binding.h" -#include "V8CustomEventListener.h" -#include "V8SVGPODTypeWrapper.h" -#include "V8Proxy.h" - -namespace WebCore { - -v8::Handle<v8::Value> V8SVGElementInstance::addEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.SVGElementInstance.AddEventListener()"); - SVGElementInstance* instance = V8SVGElementInstance::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(instance, args[1], false, ListenerFindOrCreate); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - instance->addEventListener(type, listener, useCapture); - createHiddenDependency(args.Holder(), args[1], cacheIndex); - } - - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8SVGElementInstance::removeEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.SVGElementInstance.RemoveEventListener()"); - SVGElementInstance* instance = V8SVGElementInstance::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(instance, args[1], false, ListenerFindOnly); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - instance->removeEventListener(type, listener.get(), useCapture); - removeHiddenDependency(args.Holder(), args[1], cacheIndex); - } - - return v8::Undefined(); -} - -} // namespace WebCore - -#endif diff --git a/WebCore/bindings/v8/custom/V8SVGPathSegCustom.cpp b/WebCore/bindings/v8/custom/V8SVGPathSegCustom.cpp index a96d55e..5544f83 100644 --- a/WebCore/bindings/v8/custom/V8SVGPathSegCustom.cpp +++ b/WebCore/bindings/v8/custom/V8SVGPathSegCustom.cpp @@ -29,6 +29,8 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "V8SVGPathSeg.h" #include "V8DOMWindow.h" @@ -104,3 +106,5 @@ v8::Handle<v8::Value> toV8(SVGPathSeg* impl) } } // namespace WebCore + +#endif diff --git a/WebCore/bindings/v8/custom/V8BarInfoCustom.cpp b/WebCore/bindings/v8/custom/V8ScriptProfileCustom.cpp index 44f0b62..ddaabb0 100644 --- a/WebCore/bindings/v8/custom/V8BarInfoCustom.cpp +++ b/WebCore/bindings/v8/custom/V8ScriptProfileCustom.cpp @@ -29,45 +29,33 @@ */ #include "config.h" -#include "V8BarInfo.h" +#include "V8ScriptProfile.h" -#include "V8DOMWindow.h" -#include "V8DOMWrapper.h" +#include "ScriptProfile.h" +#include "V8Binding.h" +#include "V8Proxy.h" + +#include <v8-profiler.h> namespace WebCore { -v8::Handle<v8::Value> toV8(BarInfo* impl) +v8::Handle<v8::Value> toV8(ScriptProfile* impl) { if (!impl) return v8::Null(); - v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(impl); - if (wrapper.IsEmpty()) { - wrapper = V8BarInfo::wrap(impl); - if (!wrapper.IsEmpty()) { - Frame* frame = impl->frame(); - switch (impl->type()) { - case BarInfo::Locationbar: - V8DOMWrapper::setHiddenWindowReference(frame, V8DOMWindow::locationbarIndex, wrapper); - break; - case BarInfo::Menubar: - V8DOMWrapper::setHiddenWindowReference(frame, V8DOMWindow::menubarIndex, wrapper); - break; - case BarInfo::Personalbar: - V8DOMWrapper::setHiddenWindowReference(frame, V8DOMWindow::personalbarIndex, wrapper); - break; - case BarInfo::Scrollbars: - V8DOMWrapper::setHiddenWindowReference(frame, V8DOMWindow::scrollbarsIndex, wrapper); - break; - case BarInfo::Statusbar: - V8DOMWrapper::setHiddenWindowReference(frame, V8DOMWindow::statusbarIndex, wrapper); - break; - case BarInfo::Toolbar: - V8DOMWrapper::setHiddenWindowReference(frame, V8DOMWindow::toolbarIndex, wrapper); - break; - } - } + v8::Local<v8::Function> function = V8ScriptProfile::GetTemplate()->GetFunction(); + if (function.IsEmpty()) { + // Return if allocation failed. + return v8::Local<v8::Object>(); + } + v8::Local<v8::Object> instance = SafeAllocation::newInstance(function); + if (instance.IsEmpty()) { + // Avoid setting the wrapper if allocation failed. + return v8::Local<v8::Object>(); } - return wrapper; + impl->ref(); + V8DOMWrapper::setDOMWrapper(instance, &V8ScriptProfile::info, impl); + return instance; } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8ScriptProfileNodeCustom.cpp b/WebCore/bindings/v8/custom/V8ScriptProfileNodeCustom.cpp new file mode 100644 index 0000000..a4deeeb --- /dev/null +++ b/WebCore/bindings/v8/custom/V8ScriptProfileNodeCustom.cpp @@ -0,0 +1,81 @@ +/* + * 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 "V8ScriptProfileNode.h" + +#include "ScriptProfileNode.h" +#include "V8Binding.h" +#include "V8Proxy.h" + +#include <v8-profiler.h> + +namespace WebCore { + +v8::Handle<v8::Value> V8ScriptProfileNode::childrenAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.ScriptProfileNode.childrenAccessorGetter"); + ScriptProfileNode* imp = V8ScriptProfileNode::toNative(info.Holder()); + const ProfileNodesList& children = imp->children(); + v8::Handle<v8::Array> result = v8::Array::New(children.size()); + int index = 0; + ProfileNodesList::const_iterator end = children.end(); + for (ProfileNodesList::const_iterator iter = children.begin(); iter != end; ++iter) + result->Set(v8::Integer::New(index++), toV8(iter->get())); + return result; +} + +v8::Handle<v8::Value> V8ScriptProfileNode::callUIDAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.ScriptProfileNode.callUIDAccessorGetter"); + ScriptProfileNode* imp = V8ScriptProfileNode::toNative(info.Holder()); + return v8::Number::New(imp->callUID()); +} + +v8::Handle<v8::Value> toV8(ScriptProfileNode* impl) +{ + if (!impl) + return v8::Null(); + v8::Local<v8::Function> function = V8ScriptProfileNode::GetTemplate()->GetFunction(); + if (function.IsEmpty()) { + // Return if allocation failed. + return v8::Local<v8::Object>(); + } + v8::Local<v8::Object> instance = SafeAllocation::newInstance(function); + if (instance.IsEmpty()) { + // Avoid setting the wrapper if allocation failed. + return v8::Local<v8::Object>(); + } + impl->ref(); + V8DOMWrapper::setDOMWrapper(instance, &V8ScriptProfileNode::info, impl); + return instance; +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8SharedWorkerCustom.cpp b/WebCore/bindings/v8/custom/V8SharedWorkerCustom.cpp index f69675a..2d72c37 100644 --- a/WebCore/bindings/v8/custom/V8SharedWorkerCustom.cpp +++ b/WebCore/bindings/v8/custom/V8SharedWorkerCustom.cpp @@ -80,7 +80,7 @@ v8::Handle<v8::Value> V8SharedWorker::constructorCallback(const v8::Arguments& a // Setup the standard wrapper object internal fields. v8::Handle<v8::Object> wrapperObject = args.Holder(); - V8DOMWrapper::setDOMWrapper(wrapperObject, V8ClassIndex::SHAREDWORKER, obj.get()); + V8DOMWrapper::setDOMWrapper(wrapperObject, &info, obj.get()); obj->ref(); V8DOMWrapper::setJSWrapperForActiveDOMObject(obj.get(), v8::Persistent<v8::Object>::New(wrapperObject)); diff --git a/WebCore/bindings/v8/custom/V8StyleSheetCustom.cpp b/WebCore/bindings/v8/custom/V8StyleSheetCustom.cpp index b062cdc..b3f6ff7 100644 --- a/WebCore/bindings/v8/custom/V8StyleSheetCustom.cpp +++ b/WebCore/bindings/v8/custom/V8StyleSheetCustom.cpp @@ -31,6 +31,7 @@ #include "config.h" #include "V8StyleSheet.h" +#include "V8DOMWrapper.h" #include "V8CSSStyleSheet.h" #include "V8Node.h" @@ -45,10 +46,8 @@ v8::Handle<v8::Value> toV8(StyleSheet* impl) v8::Handle<v8::Object> wrapper = V8StyleSheet::wrap(impl); // Add a hidden reference from stylesheet object to its owner node. Node* ownerNode = impl->ownerNode(); - if (ownerNode && !wrapper.IsEmpty()) { - v8::Handle<v8::Object> owner = v8::Handle<v8::Object>::Cast(toV8(ownerNode)); - wrapper->SetInternalField(V8StyleSheet::ownerNodeIndex, owner); - } + if (ownerNode && !wrapper.IsEmpty()) + V8DOMWrapper::setHiddenReference(wrapper, toV8(ownerNode)); return wrapper; } diff --git a/WebCore/bindings/v8/custom/V8WebGLArrayBufferCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLArrayBufferCustom.cpp index 5b54563..d3e6cb5 100644 --- a/WebCore/bindings/v8/custom/V8WebGLArrayBufferCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebGLArrayBufferCustom.cpp @@ -72,9 +72,13 @@ v8::Handle<v8::Value> V8WebGLArrayBuffer::constructorCallback(const v8::Argument len = toInt32(args[0]); } - RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(len); + RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(len, 1); + if (!buffer.get()) { + V8Proxy::setDOMException(INDEX_SIZE_ERR); + return v8::Undefined(); + } // Transform the holder into a wrapper object for the array. - V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::WEBGLARRAYBUFFER), buffer.get()); + V8DOMWrapper::setDOMWrapper(args.Holder(), &info, buffer.get()); return toV8(buffer.release(), args.Holder()); } diff --git a/WebCore/bindings/v8/custom/V8WebGLArrayCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLArrayCustom.cpp index a92e4f2..e15fa11 100644 --- a/WebCore/bindings/v8/custom/V8WebGLArrayCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebGLArrayCustom.cpp @@ -33,6 +33,8 @@ #if ENABLE(3D_CANVAS) #include "V8WebGLArray.h" +#include "V8Binding.h" +#include "V8Proxy.h" #include "V8WebGLByteArray.h" #include "V8WebGLFloatArray.h" #include "V8WebGLIntArray.h" @@ -64,6 +66,30 @@ v8::Handle<v8::Value> toV8(WebGLArray* impl) return v8::Handle<v8::Value>(); } +v8::Handle<v8::Value> V8WebGLArray::sliceCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.WebGLArray.slice"); + // Forms: + // * slice(long start, long end); + + WebGLArray* imp = V8WebGLArray::toNative(args.Holder()); + int start, end; + switch (args.Length()) { + case 0: + start = 0; + end = imp->length(); + break; + case 1: + start = toInt32(args[0]); + end = imp->length(); + break; + default: + start = toInt32(args[0]); + end = toInt32(args[1]); + } + return toV8(imp->slice(start, end)); +} + } // namespace WebCore #endif // ENABLE(3D_CANVAS) diff --git a/WebCore/bindings/v8/custom/V8WebGLArrayCustom.h b/WebCore/bindings/v8/custom/V8WebGLArrayCustom.h index beea8e6..02bce9c 100644 --- a/WebCore/bindings/v8/custom/V8WebGLArrayCustom.h +++ b/WebCore/bindings/v8/custom/V8WebGLArrayCustom.h @@ -41,9 +41,8 @@ namespace WebCore { // Template function used by the WebGLArray*Constructor callbacks. -template<class ArrayClass> -v8::Handle<v8::Value> constructWebGLArray(const v8::Arguments& args, - int classIndex) +template<class ArrayClass, class ElementType> +v8::Handle<v8::Value> constructWebGLArray(const v8::Arguments& args, WrapperTypeInfo* type, v8::ExternalArrayType arrayType) { if (!args.IsConstructCall()) return throwError("DOM object constructor cannot be called as a function."); @@ -71,96 +70,64 @@ v8::Handle<v8::Value> constructWebGLArray(const v8::Arguments& args, // See whether the first argument is a WebGLArrayBuffer. if (V8WebGLArrayBuffer::HasInstance(args[0])) { - if (argLen > 3) - return throwError("Wrong number of arguments to new WebGL<T>Array(WebGLArrayBuffer, int, int)"); - WebGLArrayBuffer* buf = V8WebGLArrayBuffer::toNative(args[0]->ToObject()); - if (buf == NULL) + if (!buf) return throwError("Could not convert argument 0 to a WebGLArrayBuffer"); bool ok; - int offset = 0; + uint32_t offset = 0; if (argLen > 1) { - offset = toInt32(args[1], ok); + offset = toUInt32(args[1], ok); if (!ok) - return throwError("Could not convert argument 1 to an integer"); + return throwError("Could not convert argument 1 to a number"); } - int length = buf->byteLength() - offset; + uint32_t length = (buf->byteLength() - offset) / sizeof(ElementType); if (argLen > 2) { - length = toInt32(args[2], ok); + length = toUInt32(args[2], ok); if (!ok) - return throwError("Could not convert argument 2 to an integer"); + return throwError("Could not convert argument 2 to a number"); } - if (length < 0) - return throwError("Length / offset out of range"); RefPtr<ArrayClass> array = ArrayClass::create(buf, offset, length); - if (array == NULL) - return throwError("Invalid arguments to new WebGL<T>Array(WebGLArrayBuffer, int, int)"); + if (!array) + return throwError("Out-of-range offset and/or length"); // Transform the holder into a wrapper object for the array. - V8DOMWrapper::setDOMWrapper(args.Holder(), classIndex, array.get()); - V8DOMWrapper::setIndexedPropertiesToExternalArray(args.Holder(), - classIndex, - array.get()->baseAddress(), - array.get()->length()); + V8DOMWrapper::setDOMWrapper(args.Holder(), type, array.get()); + args.Holder()->SetIndexedPropertiesToExternalArrayData(array.get()->baseAddress(), arrayType, array.get()->length()); return toV8(array.release(), args.Holder()); } - int len = 0; + uint32_t len = 0; v8::Handle<v8::Object> srcArray; - if (argLen != 1) - return throwError("Wrong number of arguments to new WebGL<T>Array(int / array)"); if (args[0]->IsInt32()) { - len = toInt32(args[0]); + len = toUInt32(args[0]); } else if (args[0]->IsObject()) { srcArray = args[0]->ToObject(); if (srcArray.IsEmpty()) - return throwError("Could not convert argument 0 to an object"); - len = toInt32(srcArray->Get(v8::String::New("length"))); + return throwError("Could not convert argument 0 to an array"); + len = toUInt32(srcArray->Get(v8::String::New("length"))); } else - return throwError("Could not convert argument 0 to either an int32 or an object"); + return throwError("Could not convert argument 0 to either a number or an array"); RefPtr<ArrayClass> array = ArrayClass::create(len); + if (!array.get()) { + V8Proxy::setDOMException(INDEX_SIZE_ERR); + return v8::Undefined(); + } if (!srcArray.IsEmpty()) { // Need to copy the incoming array into the newly created WebGLArray. - for (int i = 0; i < len; i++) { - v8::Local<v8::Value> val = srcArray->Get(v8::Integer::New(i)); + for (unsigned i = 0; i < len; i++) { + v8::Local<v8::Value> val = srcArray->Get(v8::Integer::NewFromUnsigned(i)); array->set(i, val->NumberValue()); } } // Transform the holder into a wrapper object for the array. - V8DOMWrapper::setDOMWrapper(args.Holder(), classIndex, array.get()); - V8DOMWrapper::setIndexedPropertiesToExternalArray(args.Holder(), - classIndex, - array.get()->baseAddress(), - array.get()->length()); + V8DOMWrapper::setDOMWrapper(args.Holder(), type, array.get()); + args.Holder()->SetIndexedPropertiesToExternalArrayData(array.get()->baseAddress(), arrayType, array.get()->length()); return toV8(array.release(), args.Holder()); } -template <class T, typename ElementType> -v8::Handle<v8::Value> getWebGLArrayElement(const v8::Arguments& args, - V8ClassIndex::V8WrapperType wrapperType) -{ - if (args.Length() != 1) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - bool ok; - uint32_t index = toInt32(args[0], ok); - if (!ok) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - T* array = reinterpret_cast<T*>(args.Holder()->GetPointerFromInternalField(v8DOMWrapperObjectIndex)); - if (index >= array->length()) - return v8::Undefined(); - ElementType result; - if (!array->get(index, result)) - return v8::Undefined(); - return v8::Number::New(result); -} - template <class T> v8::Handle<v8::Value> setWebGLArrayFromArray(T* webGLArray, const v8::Arguments& args) { @@ -169,21 +136,23 @@ v8::Handle<v8::Value> setWebGLArrayFromArray(T* webGLArray, const v8::Arguments& v8::Local<v8::Object> array = args[0]->ToObject(); uint32_t offset = 0; if (args.Length() == 2) - offset = toInt32(args[1]); - uint32_t length = toInt32(array->Get(v8::String::New("length"))); - if (offset + length > webGLArray->length()) + offset = toUInt32(args[1]); + uint32_t length = toUInt32(array->Get(v8::String::New("length"))); + if (offset > webGLArray->length() || + offset + length > webGLArray->length() || + offset + length < offset) + // Out of range offset or overflow V8Proxy::setDOMException(INDEX_SIZE_ERR); else for (uint32_t i = 0; i < length; i++) - webGLArray->set(offset + i, array->Get(v8::Integer::New(i))->NumberValue()); + webGLArray->set(offset + i, array->Get(v8::Integer::NewFromUnsigned(i))->NumberValue()); } return v8::Undefined(); } template <class CPlusPlusArrayType, class JavaScriptWrapperArrayType> -v8::Handle<v8::Value> setWebGLArray(const v8::Arguments& args, - V8ClassIndex::V8WrapperType wrapperType) +v8::Handle<v8::Value> setWebGLArray(const v8::Arguments& args) { if (args.Length() < 1 || args.Length() > 2) { V8Proxy::setDOMException(SYNTAX_ERR); @@ -192,9 +161,10 @@ v8::Handle<v8::Value> setWebGLArray(const v8::Arguments& args, CPlusPlusArrayType* array = JavaScriptWrapperArrayType::toNative(args.Holder()); + // FIXME: change to IsUInt32() when available if (args.Length() == 2 && args[0]->IsInt32()) { // void set(in unsigned long index, in {long|float} value); - uint32_t index = toInt32(args[0]); + uint32_t index = toUInt32(args[0]); array->set(index, args[1]->NumberValue()); return v8::Undefined(); } @@ -204,7 +174,7 @@ v8::Handle<v8::Value> setWebGLArray(const v8::Arguments& args, CPlusPlusArrayType* src = JavaScriptWrapperArrayType::toNative(args[0]->ToObject()); uint32_t offset = 0; if (args.Length() == 2) - offset = toInt32(args[1]); + offset = toUInt32(args[1]); ExceptionCode ec = 0; array->set(src, offset, ec); V8Proxy::setDOMException(ec); diff --git a/WebCore/bindings/v8/custom/V8WebGLByteArrayCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLByteArrayCustom.cpp index dd6163a..8487ace 100644 --- a/WebCore/bindings/v8/custom/V8WebGLByteArrayCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebGLByteArrayCustom.cpp @@ -47,19 +47,13 @@ v8::Handle<v8::Value> V8WebGLByteArray::constructorCallback(const v8::Arguments& { INC_STATS("DOM.WebGLByteArray.Contructor"); - return constructWebGLArray<WebGLByteArray>(args, V8ClassIndex::ToInt(V8ClassIndex::WEBGLBYTEARRAY)); -} - -v8::Handle<v8::Value> V8WebGLByteArray::getCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.WebGLByteArray.get()"); - return getWebGLArrayElement<WebGLByteArray, signed char>(args, V8ClassIndex::WEBGLBYTEARRAY); + return constructWebGLArray<WebGLByteArray, signed char>(args, &info, v8::kExternalByteArray); } v8::Handle<v8::Value> V8WebGLByteArray::setCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLByteArray.set()"); - return setWebGLArray<WebGLByteArray, V8WebGLByteArray>(args, V8ClassIndex::WEBGLBYTEARRAY); + return setWebGLArray<WebGLByteArray, V8WebGLByteArray>(args); } v8::Handle<v8::Value> toV8(WebGLByteArray* impl) diff --git a/WebCore/bindings/v8/custom/V8WebGLFloatArrayCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLFloatArrayCustom.cpp index 3fb8865..77223ea 100644 --- a/WebCore/bindings/v8/custom/V8WebGLFloatArrayCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebGLFloatArrayCustom.cpp @@ -47,19 +47,13 @@ v8::Handle<v8::Value> V8WebGLFloatArray::constructorCallback(const v8::Arguments { INC_STATS("DOM.WebGLFloatArray.Contructor"); - return constructWebGLArray<WebGLFloatArray>(args, V8ClassIndex::ToInt(V8ClassIndex::WEBGLFLOATARRAY)); -} - -v8::Handle<v8::Value> V8WebGLFloatArray::getCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.WebGLFloatArray.get()"); - return getWebGLArrayElement<WebGLFloatArray, float>(args, V8ClassIndex::WEBGLFLOATARRAY); + return constructWebGLArray<WebGLFloatArray, float>(args, &info, v8::kExternalFloatArray); } v8::Handle<v8::Value> V8WebGLFloatArray::setCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLFloatArray.set()"); - return setWebGLArray<WebGLFloatArray, V8WebGLFloatArray>(args, V8ClassIndex::WEBGLFLOATARRAY); + return setWebGLArray<WebGLFloatArray, V8WebGLFloatArray>(args); } v8::Handle<v8::Value> toV8(WebGLFloatArray* impl) diff --git a/WebCore/bindings/v8/custom/V8WebGLIntArrayCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLIntArrayCustom.cpp index 0141a0b..532bdef 100644 --- a/WebCore/bindings/v8/custom/V8WebGLIntArrayCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebGLIntArrayCustom.cpp @@ -47,19 +47,13 @@ v8::Handle<v8::Value> V8WebGLIntArray::constructorCallback(const v8::Arguments& { INC_STATS("DOM.WebGLIntArray.Contructor"); - return constructWebGLArray<WebGLIntArray>(args, V8ClassIndex::ToInt(V8ClassIndex::WEBGLINTARRAY)); -} - -v8::Handle<v8::Value> V8WebGLIntArray::getCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.WebGLIntArray.get()"); - return getWebGLArrayElement<WebGLIntArray, int>(args, V8ClassIndex::WEBGLINTARRAY); + return constructWebGLArray<WebGLIntArray, int>(args, &info, v8::kExternalIntArray); } v8::Handle<v8::Value> V8WebGLIntArray::setCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLIntArray.set()"); - return setWebGLArray<WebGLIntArray, V8WebGLIntArray>(args, V8ClassIndex::WEBGLINTARRAY); + return setWebGLArray<WebGLIntArray, V8WebGLIntArray>(args); } v8::Handle<v8::Value> toV8(WebGLIntArray* impl) diff --git a/WebCore/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp index 78de5e6..1b8936d 100644 --- a/WebCore/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp @@ -2,7 +2,7 @@ * Copyright (C) 2009 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions areV8ClassIndex::WEBGL + * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright @@ -429,10 +429,6 @@ v8::Handle<v8::Value> V8WebGLRenderingContext::getUniformCallback(const v8::Argu bool ok = false; WebGLUniformLocation* location = toWebGLUniformLocation(args[1], ok); - if (!ok) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } WebGLGetInfo info = context->getUniform(program, location, ec); if (ec) { V8Proxy::setDOMException(ec); @@ -786,10 +782,6 @@ static v8::Handle<v8::Value> vertexAttribAndUniformHelperf(const v8::Arguments& WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder()); - if (!ok) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } if (V8WebGLFloatArray::HasInstance(args[1])) { WebGLFloatArray* array = V8WebGLFloatArray::toNative(args[1]->ToObject()); ASSERT(array != NULL); @@ -862,10 +854,6 @@ static v8::Handle<v8::Value> uniformHelperi(const v8::Arguments& args, bool ok = false; WebGLUniformLocation* location = toWebGLUniformLocation(args[0], ok); - if (!ok) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } if (V8WebGLIntArray::HasInstance(args[1])) { WebGLIntArray* array = V8WebGLIntArray::toNative(args[1]->ToObject()); ASSERT(array != NULL); @@ -979,10 +967,6 @@ static v8::Handle<v8::Value> uniformMatrixHelper(const v8::Arguments& args, bool ok = false; WebGLUniformLocation* location = toWebGLUniformLocation(args[0], ok); - if (!ok) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } bool transpose = args[1]->BooleanValue(); if (V8WebGLFloatArray::HasInstance(args[2])) { WebGLFloatArray* array = V8WebGLFloatArray::toNative(args[2]->ToObject()); diff --git a/WebCore/bindings/v8/custom/V8WebGLShortArrayCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLShortArrayCustom.cpp index 5a2408e..328f227 100644 --- a/WebCore/bindings/v8/custom/V8WebGLShortArrayCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebGLShortArrayCustom.cpp @@ -47,19 +47,13 @@ v8::Handle<v8::Value> V8WebGLShortArray::constructorCallback(const v8::Arguments { INC_STATS("DOM.WebGLShortArray.Contructor"); - return constructWebGLArray<WebGLShortArray>(args, V8ClassIndex::ToInt(V8ClassIndex::WEBGLSHORTARRAY)); -} - -v8::Handle<v8::Value> V8WebGLShortArray::getCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.WebGLShortArray.get()"); - return getWebGLArrayElement<WebGLShortArray, short>(args, V8ClassIndex::WEBGLSHORTARRAY); + return constructWebGLArray<WebGLShortArray, short>(args, &info, v8::kExternalShortArray); } v8::Handle<v8::Value> V8WebGLShortArray::setCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLShortArray.set()"); - return setWebGLArray<WebGLShortArray, V8WebGLShortArray>(args, V8ClassIndex::WEBGLSHORTARRAY); + return setWebGLArray<WebGLShortArray, V8WebGLShortArray>(args); } v8::Handle<v8::Value> toV8(WebGLShortArray* impl) diff --git a/WebCore/bindings/v8/custom/V8WebGLUnsignedByteArrayCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLUnsignedByteArrayCustom.cpp index 5a30ace..5185298 100644 --- a/WebCore/bindings/v8/custom/V8WebGLUnsignedByteArrayCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebGLUnsignedByteArrayCustom.cpp @@ -47,19 +47,13 @@ v8::Handle<v8::Value> V8WebGLUnsignedByteArray::constructorCallback(const v8::Ar { INC_STATS("DOM.WebGLUnsignedByteArray.Contructor"); - return constructWebGLArray<WebGLUnsignedByteArray>(args, V8ClassIndex::ToInt(V8ClassIndex::WEBGLUNSIGNEDBYTEARRAY)); -} - -v8::Handle<v8::Value> V8WebGLUnsignedByteArray::getCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.WebGLUnsignedByteArray.get()"); - return getWebGLArrayElement<WebGLUnsignedByteArray, unsigned char>(args, V8ClassIndex::WEBGLUNSIGNEDBYTEARRAY); + return constructWebGLArray<WebGLUnsignedByteArray, unsigned char>(args, &info, v8::kExternalUnsignedByteArray); } v8::Handle<v8::Value> V8WebGLUnsignedByteArray::setCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLUnsignedByteArray.set()"); - return setWebGLArray<WebGLUnsignedByteArray, V8WebGLUnsignedByteArray>(args, V8ClassIndex::WEBGLUNSIGNEDBYTEARRAY); + return setWebGLArray<WebGLUnsignedByteArray, V8WebGLUnsignedByteArray>(args); } v8::Handle<v8::Value> toV8(WebGLUnsignedByteArray* impl) diff --git a/WebCore/bindings/v8/custom/V8WebGLUnsignedIntArrayCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLUnsignedIntArrayCustom.cpp index cefc60e..14aa1bb 100644 --- a/WebCore/bindings/v8/custom/V8WebGLUnsignedIntArrayCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebGLUnsignedIntArrayCustom.cpp @@ -47,19 +47,13 @@ v8::Handle<v8::Value> V8WebGLUnsignedIntArray::constructorCallback(const v8::Arg { INC_STATS("DOM.WebGLUnsignedIntArray.Contructor"); - return constructWebGLArray<WebGLUnsignedIntArray>(args, V8ClassIndex::ToInt(V8ClassIndex::WEBGLUNSIGNEDINTARRAY)); -} - -v8::Handle<v8::Value> V8WebGLUnsignedIntArray::getCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.WebGLUnsignedIntArray.get()"); - return getWebGLArrayElement<WebGLUnsignedIntArray, unsigned int>(args, V8ClassIndex::WEBGLUNSIGNEDINTARRAY); + return constructWebGLArray<WebGLUnsignedIntArray, unsigned int>(args, &info, v8::kExternalUnsignedIntArray); } v8::Handle<v8::Value> V8WebGLUnsignedIntArray::setCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLUnsignedIntArray.set()"); - return setWebGLArray<WebGLUnsignedIntArray, V8WebGLUnsignedIntArray>(args, V8ClassIndex::WEBGLUNSIGNEDINTARRAY); + return setWebGLArray<WebGLUnsignedIntArray, V8WebGLUnsignedIntArray>(args); } v8::Handle<v8::Value> toV8(WebGLUnsignedIntArray* impl) diff --git a/WebCore/bindings/v8/custom/V8WebGLUnsignedShortArrayCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLUnsignedShortArrayCustom.cpp index 56e34b8..e9ebb4f 100644 --- a/WebCore/bindings/v8/custom/V8WebGLUnsignedShortArrayCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebGLUnsignedShortArrayCustom.cpp @@ -47,19 +47,13 @@ v8::Handle<v8::Value> V8WebGLUnsignedShortArray::constructorCallback(const v8::A { INC_STATS("DOM.WebGLUnsignedShortArray.Contructor"); - return constructWebGLArray<WebGLUnsignedShortArray>(args, V8ClassIndex::ToInt(V8ClassIndex::WEBGLUNSIGNEDSHORTARRAY)); -} - -v8::Handle<v8::Value> V8WebGLUnsignedShortArray::getCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.WebGLUnsignedShortArray.get()"); - return getWebGLArrayElement<WebGLUnsignedShortArray, unsigned short>(args, V8ClassIndex::WEBGLUNSIGNEDSHORTARRAY); + return constructWebGLArray<WebGLUnsignedShortArray, unsigned short>(args, &info, v8::kExternalUnsignedShortArray); } v8::Handle<v8::Value> V8WebGLUnsignedShortArray::setCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLUnsignedShortArray.set()"); - return setWebGLArray<WebGLUnsignedShortArray, V8WebGLUnsignedShortArray>(args, V8ClassIndex::WEBGLUNSIGNEDSHORTARRAY); + return setWebGLArray<WebGLUnsignedShortArray, V8WebGLUnsignedShortArray>(args); } v8::Handle<v8::Value> toV8(WebGLUnsignedShortArray* impl) diff --git a/WebCore/bindings/v8/custom/V8WebKitCSSMatrixConstructor.cpp b/WebCore/bindings/v8/custom/V8WebKitCSSMatrixConstructor.cpp index 55518d2..b97d0e8 100644 --- a/WebCore/bindings/v8/custom/V8WebKitCSSMatrixConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8WebKitCSSMatrixConstructor.cpp @@ -63,7 +63,7 @@ v8::Handle<v8::Value> V8WebKitCSSMatrix::constructorCallback(const v8::Arguments throwError(ec); // Transform the holder into a wrapper object for the matrix. - V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::WEBKITCSSMATRIX), matrix.get()); + V8DOMWrapper::setDOMWrapper(args.Holder(), &info, matrix.get()); return toV8(matrix.release(), args.Holder()); } diff --git a/WebCore/bindings/v8/custom/V8WebKitPointConstructor.cpp b/WebCore/bindings/v8/custom/V8WebKitPointConstructor.cpp index 1959454..cb29f82 100755 --- a/WebCore/bindings/v8/custom/V8WebKitPointConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8WebKitPointConstructor.cpp @@ -33,8 +33,8 @@ #include "V8Binding.h" #include "V8DOMWrapper.h" -#include "V8Index.h" #include "V8Proxy.h" +#include "WrapperTypeInfo.h" #include <wtf/MathExtras.h> @@ -63,7 +63,7 @@ v8::Handle<v8::Value> V8WebKitPoint::constructorCallback(const v8::Arguments& ar } PassRefPtr<WebKitPoint> point = WebKitPoint::create(x, y); point->ref(); - V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::WEBKITPOINT, point.get()); + V8DOMWrapper::setDOMWrapper(args.Holder(), &info, point.get()); return args.Holder(); } diff --git a/WebCore/bindings/v8/custom/V8WebSocketCustom.cpp b/WebCore/bindings/v8/custom/V8WebSocketCustom.cpp index 2451b90..b931053 100644 --- a/WebCore/bindings/v8/custom/V8WebSocketCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebSocketCustom.cpp @@ -45,37 +45,6 @@ namespace WebCore { -v8::Handle<v8::Value> V8WebSocket::addEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.WebSocket.addEventListener()"); - WebSocket* webSocket = V8WebSocket::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(webSocket, args[1], false, ListenerFindOrCreate); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - webSocket->addEventListener(type, listener, useCapture); - - createHiddenDependency(args.Holder(), args[1], cacheIndex); - } - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8WebSocket::removeEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.WebSocket.removeEventListener()"); - WebSocket* webSocket = V8WebSocket::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(webSocket, args[1], false, ListenerFindOnly); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - webSocket->removeEventListener(type, listener.get(), useCapture); - removeHiddenDependency(args.Holder(), args[1], cacheIndex); - } - return v8::Undefined(); -} - v8::Handle<v8::Value> V8WebSocket::constructorCallback(const v8::Arguments& args) { INC_STATS("DOM.WebSocket.Constructor"); @@ -115,7 +84,7 @@ v8::Handle<v8::Value> V8WebSocket::constructorCallback(const v8::Arguments& args return throwError(ec); // Setup the standard wrapper object internal fields. - V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::WEBSOCKET), webSocket.get()); + V8DOMWrapper::setDOMWrapper(args.Holder(), &info, webSocket.get()); // Add object to the wrapper map. webSocket->ref(); diff --git a/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp b/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp index 7677e27..46bd966 100755 --- a/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp @@ -58,7 +58,11 @@ v8::Handle<v8::Value> SetTimeoutOrInterval(const v8::Arguments& args, bool singl int32_t timeout = argumentCount >= 2 ? args[1]->Int32Value() : 0; int timerId; - v8::Handle<v8::Context> v8Context = workerContext->script()->proxy()->context(); + WorkerContextExecutionProxy* proxy = workerContext->script()->proxy(); + if (!proxy) + return v8::Undefined(); + + v8::Handle<v8::Context> v8Context = proxy->context(); if (function->IsString()) { WebCore::String stringFunction = toWebCoreString(function); timerId = DOMTimer::install(workerContext, new ScheduledAction(v8Context, stringFunction, workerContext->url()), timeout, singleShot); @@ -86,14 +90,6 @@ v8::Handle<v8::Value> V8WorkerContext::importScriptsCallback(const v8::Arguments if (!args.Length()) return v8::Undefined(); - String callerURL; - if (!V8Proxy::sourceName(callerURL)) - return v8::Undefined(); - int callerLine; - if (!V8Proxy::sourceLineNumber(callerLine)) - return v8::Undefined(); - callerLine += 1; - Vector<String> urls; for (int i = 0; i < args.Length(); i++) { v8::TryCatch tryCatch; @@ -106,7 +102,7 @@ v8::Handle<v8::Value> V8WorkerContext::importScriptsCallback(const v8::Arguments WorkerContext* workerContext = V8WorkerContext::toNative(args.Holder()); ExceptionCode ec = 0; - workerContext->importScripts(urls, callerURL, callerLine, ec); + workerContext->importScripts(urls, ec); if (ec) return throwError(ec); @@ -126,44 +122,16 @@ v8::Handle<v8::Value> V8WorkerContext::setIntervalCallback(const v8::Arguments& return SetTimeoutOrInterval(args, false); } -v8::Handle<v8::Value> V8WorkerContext::addEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS(L"DOM.WorkerContext.addEventListener()"); - WorkerContext* workerContext = V8WorkerContext::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(workerContext, args[1], false, ListenerFindOrCreate); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - workerContext->addEventListener(type, listener, useCapture); - - createHiddenDependency(args.Holder(), args[1], cacheIndex); - } - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8WorkerContext::removeEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS(L"DOM.WorkerContext.removeEventListener()"); - WorkerContext* workerContext = V8WorkerContext::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(workerContext, args[1], false, ListenerFindOnly); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - workerContext->removeEventListener(type, listener.get(), useCapture); - - removeHiddenDependency(args.Holder(), args[1], cacheIndex); - } - return v8::Undefined(); -} - v8::Handle<v8::Value> toV8(WorkerContext* impl) { if (!impl) return v8::Null(); - v8::Handle<v8::Object> global = impl->script()->proxy()->context()->Global(); + WorkerContextExecutionProxy* proxy = impl->script()->proxy(); + if (!proxy) + return v8::Null(); + + v8::Handle<v8::Object> global = proxy->context()->Global(); ASSERT(!global.IsEmpty()); return global; } diff --git a/WebCore/bindings/v8/custom/V8WorkerCustom.cpp b/WebCore/bindings/v8/custom/V8WorkerCustom.cpp index 6b41246..fdc6815 100755 --- a/WebCore/bindings/v8/custom/V8WorkerCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WorkerCustom.cpp @@ -79,7 +79,7 @@ v8::Handle<v8::Value> V8Worker::constructorCallback(const v8::Arguments& args) // Setup the standard wrapper object internal fields. v8::Handle<v8::Object> wrapperObject = args.Holder(); - V8DOMWrapper::setDOMWrapper(wrapperObject, V8ClassIndex::WORKER, obj.get()); + V8DOMWrapper::setDOMWrapper(wrapperObject, &info, obj.get()); obj->ref(); V8DOMWrapper::setJSWrapperForActiveDOMObject(obj.get(), v8::Persistent<v8::Object>::New(wrapperObject)); @@ -91,7 +91,10 @@ v8::Handle<v8::Value> V8Worker::postMessageCallback(const v8::Arguments& args) { INC_STATS("DOM.Worker.postMessage"); Worker* worker = V8Worker::toNative(args.Holder()); - RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(args[0]); + bool didThrow = false; + RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(args[0], didThrow); + if (didThrow) + return v8::Undefined(); MessagePortArray portArray; if (args.Length() > 1) { if (!getMessagePortArray(args[1], portArray)) diff --git a/WebCore/bindings/v8/custom/V8XMLHttpRequestConstructor.cpp b/WebCore/bindings/v8/custom/V8XMLHttpRequestConstructor.cpp index f50248b..6b5b64f 100644 --- a/WebCore/bindings/v8/custom/V8XMLHttpRequestConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8XMLHttpRequestConstructor.cpp @@ -53,7 +53,7 @@ v8::Handle<v8::Value> V8XMLHttpRequest::constructorCallback(const v8::Arguments& if (!context) return throwError("XMLHttpRequest constructor's associated context is not available", V8Proxy::ReferenceError); RefPtr<XMLHttpRequest> xmlHttpRequest = XMLHttpRequest::create(context); - V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::XMLHTTPREQUEST), xmlHttpRequest.get()); + V8DOMWrapper::setDOMWrapper(args.Holder(), &info, xmlHttpRequest.get()); // Add object to the wrapper map. xmlHttpRequest->ref(); diff --git a/WebCore/bindings/v8/custom/V8XMLHttpRequestCustom.cpp b/WebCore/bindings/v8/custom/V8XMLHttpRequestCustom.cpp index d10c418..4e9c715 100644 --- a/WebCore/bindings/v8/custom/V8XMLHttpRequestCustom.cpp +++ b/WebCore/bindings/v8/custom/V8XMLHttpRequestCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009 Google Inc. All rights reserved. + * Copyright (C) 2008, 2009, 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 @@ -34,6 +34,7 @@ #include "Frame.h" #include "V8Binding.h" #include "V8Blob.h" +#include "V8DOMFormData.h" #include "V8Document.h" #include "V8HTMLDocument.h" #include "V8Proxy.h" @@ -51,39 +52,6 @@ v8::Handle<v8::Value> V8XMLHttpRequest::responseTextAccessorGetter(v8::Local<v8: return xmlHttpRequest->responseText().v8StringOrNull(); } -v8::Handle<v8::Value> V8XMLHttpRequest::addEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.XMLHttpRequest.addEventListener()"); - XMLHttpRequest* xmlHttpRequest = V8XMLHttpRequest::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(xmlHttpRequest, args[1], false, ListenerFindOrCreate); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - xmlHttpRequest->addEventListener(type, listener, useCapture); - - createHiddenDependency(args.Holder(), args[1], cacheIndex); - } - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8XMLHttpRequest::removeEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.XMLHttpRequest.removeEventListener()"); - XMLHttpRequest* xmlHttpRequest = V8XMLHttpRequest::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(xmlHttpRequest, args[1], false, ListenerFindOnly); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - xmlHttpRequest->removeEventListener(type, listener.get(), useCapture); - - removeHiddenDependency(args.Holder(), args[1], cacheIndex); - } - - return v8::Undefined(); -} - v8::Handle<v8::Value> V8XMLHttpRequest::openCallback(const v8::Arguments& args) { INC_STATS("DOM.XMLHttpRequest.open()"); @@ -106,20 +74,23 @@ v8::Handle<v8::Value> V8XMLHttpRequest::openCallback(const v8::Arguments& args) KURL url = context->completeURL(urlstring); - bool async = (args.Length() < 3) ? true : args[2]->BooleanValue(); - ExceptionCode ec = 0; - String user, passwd; - if (args.Length() >= 4 && !args[3]->IsUndefined()) { - user = toWebCoreStringWithNullCheck(args[3]); - if (args.Length() >= 5 && !args[4]->IsUndefined()) { - passwd = toWebCoreStringWithNullCheck(args[4]); - xmlHttpRequest->open(method, url, async, user, passwd, ec); + if (args.Length() >= 3) { + bool async = args[2]->BooleanValue(); + + if (args.Length() >= 4 && !args[3]->IsUndefined()) { + String user = toWebCoreStringWithNullCheck(args[3]); + + if (args.Length() >= 5 && !args[4]->IsUndefined()) { + String passwd = toWebCoreStringWithNullCheck(args[4]); + xmlHttpRequest->open(method, url, async, user, passwd, ec); + } else + xmlHttpRequest->open(method, url, async, user, ec); } else - xmlHttpRequest->open(method, url, async, user, ec); + xmlHttpRequest->open(method, url, async, ec); } else - xmlHttpRequest->open(method, url, async, ec); + xmlHttpRequest->open(method, url, ec); if (ec) return throwError(ec); @@ -127,7 +98,7 @@ v8::Handle<v8::Value> V8XMLHttpRequest::openCallback(const v8::Arguments& args) return v8::Undefined(); } -static bool IsDocumentType(v8::Handle<v8::Value> value) +static bool isDocumentType(v8::Handle<v8::Value> value) { // FIXME: add other document types. return V8Document::HasInstance(value) || V8HTMLDocument::HasInstance(value); @@ -143,7 +114,9 @@ v8::Handle<v8::Value> V8XMLHttpRequest::sendCallback(const v8::Arguments& args) xmlHttpRequest->send(ec); else { v8::Handle<v8::Value> arg = args[0]; - if (IsDocumentType(arg)) { + if (isUndefinedOrNull(arg)) + xmlHttpRequest->send(ec); + else if (isDocumentType(arg)) { v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg); Document* document = V8Document::toNative(object); ASSERT(document); @@ -153,6 +126,11 @@ v8::Handle<v8::Value> V8XMLHttpRequest::sendCallback(const v8::Arguments& args) Blob* blob = V8Blob::toNative(object); ASSERT(blob); xmlHttpRequest->send(blob, ec); + } else if (V8DOMFormData::HasInstance(arg)) { + v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg); + DOMFormData* domFormData = V8DOMFormData::toNative(object); + ASSERT(domFormData); + xmlHttpRequest->send(domFormData, ec); } else xmlHttpRequest->send(toWebCoreStringWithNullCheck(arg), ec); } @@ -206,10 +184,4 @@ v8::Handle<v8::Value> V8XMLHttpRequest::overrideMimeTypeCallback(const v8::Argum return v8::Undefined(); } -v8::Handle<v8::Value> V8XMLHttpRequest::dispatchEventCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.XMLHttpRequest.dispatchEvent()"); - return v8::Undefined(); -} - } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8XMLHttpRequestUploadCustom.cpp b/WebCore/bindings/v8/custom/V8XMLHttpRequestUploadCustom.cpp deleted file mode 100644 index c6c31bf..0000000 --- a/WebCore/bindings/v8/custom/V8XMLHttpRequestUploadCustom.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2008, 2009 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 "V8XMLHttpRequestUpload.h" - -#include "ExceptionCode.h" -#include "V8Binding.h" -#include "V8Proxy.h" -#include "V8Utilities.h" -#include "XMLHttpRequest.h" -#include "XMLHttpRequestUpload.h" - -#include <wtf/Assertions.h> - -namespace WebCore { - -v8::Handle<v8::Value> V8XMLHttpRequestUpload::addEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.XMLHttpRequestUpload.addEventListener()"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8XMLHttpRequestUpload::toNative(args.Holder()); - - XMLHttpRequest* xmlHttpRequest = xmlHttpRequestUpload->associatedXMLHttpRequest(); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(xmlHttpRequest, args[1], false, ListenerFindOrCreate); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - xmlHttpRequestUpload->addEventListener(type, listener, useCapture); - - createHiddenDependency(args.Holder(), args[1], cacheIndex); - } - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8XMLHttpRequestUpload::removeEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.XMLHttpRequestUpload.removeEventListener()"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8XMLHttpRequestUpload::toNative(args.Holder()); - - XMLHttpRequest* xmlHttpRequest = xmlHttpRequestUpload->associatedXMLHttpRequest(); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(xmlHttpRequest, args[1], false, ListenerFindOnly); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - xmlHttpRequestUpload->removeEventListener(type, listener.get(), useCapture); - - removeHiddenDependency(args.Holder(), args[1], cacheIndex); - } - - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8XMLHttpRequestUpload::dispatchEventCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.XMLHttpRequestUpload.dispatchEvent()"); - return throwError(NOT_SUPPORTED_ERR); -} - -} // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8XSLTProcessorCustom.cpp b/WebCore/bindings/v8/custom/V8XSLTProcessorCustom.cpp index 89f804c..b624fcf 100644 --- a/WebCore/bindings/v8/custom/V8XSLTProcessorCustom.cpp +++ b/WebCore/bindings/v8/custom/V8XSLTProcessorCustom.cpp @@ -49,7 +49,7 @@ namespace WebCore { v8::Handle<v8::Value> V8XSLTProcessor::constructorCallback(const v8::Arguments& args) { INC_STATS("DOM.XSLTProcessor.Constructor"); - return V8Proxy::constructDOMObject<V8ClassIndex::XSLTPROCESSOR, XSLTProcessor>(args); + return V8Proxy::constructDOMObject<XSLTProcessor>(args, &info); } diff --git a/WebCore/bindings/v8/test/TestObj.idl b/WebCore/bindings/v8/test/TestObj.idl new file mode 100644 index 0000000..662ac64 --- /dev/null +++ b/WebCore/bindings/v8/test/TestObj.idl @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary formstrArg, 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. + * 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 WARRANTIEstrArg, 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. + */ + +// This IDL file is for testing the V8 generator and for tracking changes +// in its ouput. +module test { + interface TestObj { + // Attributes + readonly attribute long readOnlyIntAttr; + readonly attribute DOMString readOnlyStringAttr; + readonly attribute TestObj readOnlyTestObjAttr; + attribute long intAttr; + attribute DOMString stringAttr; + attribute TestObj testObjAttr; + + // Methods + void voidMethod(); + void voidMethodWithArgs(in long intArg, in DOMString strArg, in TestObj objArg); + long intMethod(); + long intMethodWithArgs(in long intArg, in DOMString strArg, in TestObj objArg); + TestObj objMethod(); + TestObj objMethodWithArgs(in long intArg, in DOMString strArg, in TestObj objArg); + + // Exceptions + void methodWithException() raises(DOMException); + attribute long attrWithException raises(DOMException); + attribute long attrWithSetterException getraises(DOMException); + attribute long attrWithGetterException setraises(DOMException); + + // 'Custom' extended attribute + attribute [Custom] long customAttr; + [Custom] void customMethod(); + [Custom] void customMethodWithArgs(in long intArg, in DOMString strArg, in TestObj objArg); + + // 'Optional' extended attribute + void methodWithOptionalArg(in [Optional] long opt); + void methodWithNonOptionalArgAndOptionalArg(in long nonOpt, in [Optional] long opt); + void methodWithNonOptionalArgAndTwoOptionalArgs(in long nonOpt, in [Optional] long opt1, in long opt2); + + // Overloads + void overloadedMethod(in TestObj objArg, in DOMString strArg); + void overloadedMethod(in TestObj objArg, in [Optional] long intArg); + void overloadedMethod(in DOMString strArg); + void overloadedMethod(in long intArg); + }; +} diff --git a/WebCore/bindings/v8/test/V8TestObj.cpp b/WebCore/bindings/v8/test/V8TestObj.cpp new file mode 100644 index 0000000..d51884e --- /dev/null +++ b/WebCore/bindings/v8/test/V8TestObj.cpp @@ -0,0 +1,459 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "config.h" +#include "V8TestObj.h" + +#include "ExceptionCode.h" +#include "RuntimeEnabledFeatures.h" +#include "V8Binding.h" +#include "V8BindingState.h" +#include "V8DOMWrapper.h" +#include "V8IsolatedContext.h" +#include "V8Proxy.h" +#include <wtf/GetPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +WrapperTypeInfo V8TestObj::info = { V8TestObj::GetTemplate, V8TestObj::derefObject, 0 }; + +namespace TestObjInternal { + +template <typename T> void V8_USE(T) { } + +static v8::Handle<v8::Value> readOnlyIntAttrAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.readOnlyIntAttr._get"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + return v8::Integer::New(imp->readOnlyIntAttr()); +} + +static v8::Handle<v8::Value> readOnlyStringAttrAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.readOnlyStringAttr._get"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + return v8String(imp->readOnlyStringAttr()); +} + +static v8::Handle<v8::Value> readOnlyTestObjAttrAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.readOnlyTestObjAttr._get"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + RefPtr<TestObj> result = imp->readOnlyTestObjAttr(); + v8::Handle<v8::Value> wrapper = result.get() ? getDOMObjectMap().get(result.get()) : v8::Handle<v8::Value>(); + if (wrapper.IsEmpty()) { + wrapper = toV8(result.get()); + if (!wrapper.IsEmpty()) + V8DOMWrapper::setHiddenReference(info.Holder(), wrapper); + } + return wrapper; +} + +static v8::Handle<v8::Value> intAttrAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.intAttr._get"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + return v8::Integer::New(imp->intAttr()); +} + +static void intAttrAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.intAttr._set"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + int v = toInt32(value); + imp->setIntAttr(v); + return; +} + +static v8::Handle<v8::Value> stringAttrAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.stringAttr._get"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + return v8String(imp->stringAttr()); +} + +static void stringAttrAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.stringAttr._set"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + V8Parameter<> v = value; + imp->setStringAttr(v); + return; +} + +static v8::Handle<v8::Value> testObjAttrAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.testObjAttr._get"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + return toV8(imp->testObjAttr()); +} + +static void testObjAttrAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.testObjAttr._set"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + TestObj* v = V8TestObj::HasInstance(value) ? V8TestObj::toNative(v8::Handle<v8::Object>::Cast(value)) : 0; + imp->setTestObjAttr(WTF::getPtr(v)); + return; +} + +static v8::Handle<v8::Value> attrWithExceptionAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.attrWithException._get"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + return v8::Integer::New(imp->attrWithException()); +} + +static void attrWithExceptionAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.attrWithException._set"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + int v = toInt32(value); + imp->setAttrWithException(v); + return; +} + +static v8::Handle<v8::Value> attrWithSetterExceptionAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.attrWithSetterException._get"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + return v8::Integer::New(imp->attrWithSetterException()); +} + +static void attrWithSetterExceptionAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.attrWithSetterException._set"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + int v = toInt32(value); + imp->setAttrWithSetterException(v); + return; +} + +static v8::Handle<v8::Value> attrWithGetterExceptionAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.attrWithGetterException._get"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + return v8::Integer::New(imp->attrWithGetterException()); +} + +static void attrWithGetterExceptionAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.attrWithGetterException._set"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + int v = toInt32(value); + imp->setAttrWithGetterException(v); + return; +} + +static v8::Handle<v8::Value> voidMethodCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.voidMethod"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + imp->voidMethod(); + return v8::Handle<v8::Value>(); +} + +static v8::Handle<v8::Value> voidMethodWithArgsCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.voidMethodWithArgs"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + int intArg = toInt32(args[0]); + V8Parameter<> strArg = args[1]; + TestObj* objArg = V8TestObj::HasInstance(args[2]) ? V8TestObj::toNative(v8::Handle<v8::Object>::Cast(args[2])) : 0; + imp->voidMethodWithArgs(intArg, strArg, objArg); + return v8::Handle<v8::Value>(); +} + +static v8::Handle<v8::Value> intMethodCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.intMethod"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + return v8::Integer::New(imp->intMethod()); +} + +static v8::Handle<v8::Value> intMethodWithArgsCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.intMethodWithArgs"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + int intArg = toInt32(args[0]); + V8Parameter<> strArg = args[1]; + TestObj* objArg = V8TestObj::HasInstance(args[2]) ? V8TestObj::toNative(v8::Handle<v8::Object>::Cast(args[2])) : 0; + return v8::Integer::New(imp->intMethodWithArgs(intArg, strArg, objArg)); +} + +static v8::Handle<v8::Value> objMethodCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.objMethod"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + return toV8(imp->objMethod()); +} + +static v8::Handle<v8::Value> objMethodWithArgsCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.objMethodWithArgs"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + int intArg = toInt32(args[0]); + V8Parameter<> strArg = args[1]; + TestObj* objArg = V8TestObj::HasInstance(args[2]) ? V8TestObj::toNative(v8::Handle<v8::Object>::Cast(args[2])) : 0; + return toV8(imp->objMethodWithArgs(intArg, strArg, objArg)); +} + +static v8::Handle<v8::Value> methodWithExceptionCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.methodWithException"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + ExceptionCode ec = 0; + { + imp->methodWithException(ec); + if (UNLIKELY(ec)) + goto fail; + return v8::Handle<v8::Value>(); + } + fail: + V8Proxy::setDOMException(ec); + return v8::Handle<v8::Value>(); +} + +static v8::Handle<v8::Value> methodWithOptionalArgCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.methodWithOptionalArg"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + if (args.Length() <= 0) { + imp->methodWithOptionalArg(); + return v8::Handle<v8::Value>(); + } + int opt = toInt32(args[0]); + imp->methodWithOptionalArg(opt); + return v8::Handle<v8::Value>(); +} + +static v8::Handle<v8::Value> methodWithNonOptionalArgAndOptionalArgCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.methodWithNonOptionalArgAndOptionalArg"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + int nonOpt = toInt32(args[0]); + if (args.Length() <= 1) { + imp->methodWithNonOptionalArgAndOptionalArg(nonOpt); + return v8::Handle<v8::Value>(); + } + int opt = toInt32(args[1]); + imp->methodWithNonOptionalArgAndOptionalArg(nonOpt, opt); + return v8::Handle<v8::Value>(); +} + +static v8::Handle<v8::Value> methodWithNonOptionalArgAndTwoOptionalArgsCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.methodWithNonOptionalArgAndTwoOptionalArgs"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + int nonOpt = toInt32(args[0]); + if (args.Length() <= 1) { + imp->methodWithNonOptionalArgAndTwoOptionalArgs(nonOpt); + return v8::Handle<v8::Value>(); + } + int opt1 = toInt32(args[1]); + int opt2 = toInt32(args[2]); + imp->methodWithNonOptionalArgAndTwoOptionalArgs(nonOpt, opt1, opt2); + return v8::Handle<v8::Value>(); +} + +static v8::Handle<v8::Value> overloadedMethod1Callback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.overloadedMethod1"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + TestObj* objArg = V8TestObj::HasInstance(args[0]) ? V8TestObj::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; + V8Parameter<> strArg = args[1]; + imp->overloadedMethod(objArg, strArg); + return v8::Handle<v8::Value>(); +} + +static v8::Handle<v8::Value> overloadedMethod2Callback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.overloadedMethod2"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + TestObj* objArg = V8TestObj::HasInstance(args[0]) ? V8TestObj::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; + if (args.Length() <= 1) { + imp->overloadedMethod(objArg); + return v8::Handle<v8::Value>(); + } + int intArg = toInt32(args[1]); + imp->overloadedMethod(objArg, intArg); + return v8::Handle<v8::Value>(); +} + +static v8::Handle<v8::Value> overloadedMethod3Callback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.overloadedMethod3"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + V8Parameter<> strArg = args[0]; + imp->overloadedMethod(strArg); + return v8::Handle<v8::Value>(); +} + +static v8::Handle<v8::Value> overloadedMethod4Callback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.overloadedMethod4"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + int intArg = toInt32(args[0]); + imp->overloadedMethod(intArg); + return v8::Handle<v8::Value>(); +} + +static v8::Handle<v8::Value> overloadedMethodCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.overloadedMethod"); + if ((args.Length() == 2 && (args[0]->IsNull() || V8TestObj::HasInstance(args[0])) && (args[1]->IsNull() || args[1]->IsUndefined() || args[1]->IsString() || args[1]->IsObject()))) + return overloadedMethod1Callback(args); + if ((args.Length() == 1 && (args[0]->IsNull() || V8TestObj::HasInstance(args[0]))) || (args.Length() == 2 && (args[0]->IsNull() || V8TestObj::HasInstance(args[0])))) + return overloadedMethod2Callback(args); + if ((args.Length() == 1 && (args[0]->IsNull() || args[0]->IsUndefined() || args[0]->IsString() || args[0]->IsObject()))) + return overloadedMethod3Callback(args); + if (args.Length() == 1) + return overloadedMethod4Callback(args); + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); +} + +} // namespace TestObjInternal + +static const BatchedAttribute TestObjAttrs[] = { + // Attribute 'readOnlyIntAttr' (Type: 'readonly attribute' ExtAttr: '') + {"readOnlyIntAttr", TestObjInternal::readOnlyIntAttrAttrGetter, 0, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, + // Attribute 'readOnlyStringAttr' (Type: 'readonly attribute' ExtAttr: '') + {"readOnlyStringAttr", TestObjInternal::readOnlyStringAttrAttrGetter, 0, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, + // Attribute 'readOnlyTestObjAttr' (Type: 'readonly attribute' ExtAttr: '') + {"readOnlyTestObjAttr", TestObjInternal::readOnlyTestObjAttrAttrGetter, 0, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, + // Attribute 'intAttr' (Type: 'attribute' ExtAttr: '') + {"intAttr", TestObjInternal::intAttrAttrGetter, TestObjInternal::intAttrAttrSetter, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, + // Attribute 'stringAttr' (Type: 'attribute' ExtAttr: '') + {"stringAttr", TestObjInternal::stringAttrAttrGetter, TestObjInternal::stringAttrAttrSetter, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, + // Attribute 'testObjAttr' (Type: 'attribute' ExtAttr: '') + {"testObjAttr", TestObjInternal::testObjAttrAttrGetter, TestObjInternal::testObjAttrAttrSetter, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, + // Attribute 'attrWithException' (Type: 'attribute' ExtAttr: '') + {"attrWithException", TestObjInternal::attrWithExceptionAttrGetter, TestObjInternal::attrWithExceptionAttrSetter, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, + // Attribute 'attrWithSetterException' (Type: 'attribute' ExtAttr: '') + {"attrWithSetterException", TestObjInternal::attrWithSetterExceptionAttrGetter, TestObjInternal::attrWithSetterExceptionAttrSetter, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, + // Attribute 'attrWithGetterException' (Type: 'attribute' ExtAttr: '') + {"attrWithGetterException", TestObjInternal::attrWithGetterExceptionAttrGetter, TestObjInternal::attrWithGetterExceptionAttrSetter, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, + // Attribute 'customAttr' (Type: 'attribute' ExtAttr: 'Custom') + {"customAttr", V8TestObj::customAttrAccessorGetter, V8TestObj::customAttrAccessorSetter, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, +}; +static const BatchedCallback TestObjCallbacks[] = { + {"voidMethod", TestObjInternal::voidMethodCallback}, + {"intMethod", TestObjInternal::intMethodCallback}, + {"objMethod", TestObjInternal::objMethodCallback}, + {"methodWithException", TestObjInternal::methodWithExceptionCallback}, + {"customMethod", V8TestObj::customMethodCallback}, + {"customMethodWithArgs", V8TestObj::customMethodWithArgsCallback}, + {"methodWithOptionalArg", TestObjInternal::methodWithOptionalArgCallback}, + {"methodWithNonOptionalArgAndOptionalArg", TestObjInternal::methodWithNonOptionalArgAndOptionalArgCallback}, + {"methodWithNonOptionalArgAndTwoOptionalArgs", TestObjInternal::methodWithNonOptionalArgAndTwoOptionalArgsCallback}, + {"overloadedMethod", TestObjInternal::overloadedMethodCallback}, +}; +static v8::Persistent<v8::FunctionTemplate> ConfigureV8TestObjTemplate(v8::Persistent<v8::FunctionTemplate> desc) +{ + v8::Local<v8::Signature> defaultSignature = configureTemplate(desc, "TestObj", v8::Persistent<v8::FunctionTemplate>(), V8TestObj::internalFieldCount, + TestObjAttrs, sizeof(TestObjAttrs) / sizeof(*TestObjAttrs), + TestObjCallbacks, sizeof(TestObjCallbacks) / sizeof(*TestObjCallbacks)); + v8::Local<v8::ObjectTemplate> instance = desc->InstanceTemplate(); + v8::Local<v8::ObjectTemplate> proto = desc->PrototypeTemplate(); + + + // Custom Signature 'voidMethodWithArgs' + const int voidMethodWithArgsArgc = 3; + v8::Handle<v8::FunctionTemplate> voidMethodWithArgsArgv[voidMethodWithArgsArgc] = { v8::Handle<v8::FunctionTemplate>(), v8::Handle<v8::FunctionTemplate>(), V8TestObj::GetRawTemplate() }; + v8::Handle<v8::Signature> voidMethodWithArgsSignature = v8::Signature::New(desc, voidMethodWithArgsArgc, voidMethodWithArgsArgv); + proto->Set(v8::String::New("voidMethodWithArgs"), v8::FunctionTemplate::New(TestObjInternal::voidMethodWithArgsCallback, v8::Handle<v8::Value>(), voidMethodWithArgsSignature)); + + // Custom Signature 'intMethodWithArgs' + const int intMethodWithArgsArgc = 3; + v8::Handle<v8::FunctionTemplate> intMethodWithArgsArgv[intMethodWithArgsArgc] = { v8::Handle<v8::FunctionTemplate>(), v8::Handle<v8::FunctionTemplate>(), V8TestObj::GetRawTemplate() }; + v8::Handle<v8::Signature> intMethodWithArgsSignature = v8::Signature::New(desc, intMethodWithArgsArgc, intMethodWithArgsArgv); + proto->Set(v8::String::New("intMethodWithArgs"), v8::FunctionTemplate::New(TestObjInternal::intMethodWithArgsCallback, v8::Handle<v8::Value>(), intMethodWithArgsSignature)); + + // Custom Signature 'objMethodWithArgs' + const int objMethodWithArgsArgc = 3; + v8::Handle<v8::FunctionTemplate> objMethodWithArgsArgv[objMethodWithArgsArgc] = { v8::Handle<v8::FunctionTemplate>(), v8::Handle<v8::FunctionTemplate>(), V8TestObj::GetRawTemplate() }; + v8::Handle<v8::Signature> objMethodWithArgsSignature = v8::Signature::New(desc, objMethodWithArgsArgc, objMethodWithArgsArgv); + proto->Set(v8::String::New("objMethodWithArgs"), v8::FunctionTemplate::New(TestObjInternal::objMethodWithArgsCallback, v8::Handle<v8::Value>(), objMethodWithArgsSignature)); + + // Custom toString template + desc->Set(getToStringName(), getToStringTemplate()); + return desc; +} + +v8::Persistent<v8::FunctionTemplate> V8TestObj::GetRawTemplate() +{ + static v8::Persistent<v8::FunctionTemplate> V8TestObjRawCache = createRawTemplate(); + return V8TestObjRawCache; +} + +v8::Persistent<v8::FunctionTemplate> V8TestObj::GetTemplate() +{ + static v8::Persistent<v8::FunctionTemplate> V8TestObjCache = ConfigureV8TestObjTemplate(GetRawTemplate()); + return V8TestObjCache; +} + +TestObj* V8TestObj::toNative(v8::Handle<v8::Object> object) +{ + return reinterpret_cast<TestObj*>(object->GetPointerFromInternalField(v8DOMWrapperObjectIndex)); +} + +bool V8TestObj::HasInstance(v8::Handle<v8::Value> value) +{ + return GetRawTemplate()->HasInstance(value); +} + + +v8::Handle<v8::Object> V8TestObj::wrap(TestObj* impl) +{ + v8::Handle<v8::Object> wrapper; + V8Proxy* proxy = 0; + wrapper = getDOMObjectMap().get(impl); + if (!wrapper.IsEmpty()) + return wrapper; + wrapper = V8DOMWrapper::instantiateV8Object(proxy, &info, impl); + if (wrapper.IsEmpty()) + return wrapper; + + impl->ref(); + getDOMObjectMap().set(impl, v8::Persistent<v8::Object>::New(wrapper)); + return wrapper; +} + +v8::Handle<v8::Value> toV8(PassRefPtr<TestObj > impl) +{ + return toV8(impl.get()); +} + +v8::Handle<v8::Value> toV8(TestObj* impl) +{ + if (!impl) + return v8::Null(); + return V8TestObj::wrap(impl); +} + +void V8TestObj::derefObject(void* object) +{ + static_cast<TestObj*>(object)->deref(); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/test/V8TestObj.h b/WebCore/bindings/v8/test/V8TestObj.h new file mode 100644 index 0000000..5d6770a --- /dev/null +++ b/WebCore/bindings/v8/test/V8TestObj.h @@ -0,0 +1,53 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef V8TestObj_h +#define V8TestObj_h + +#include "StringHash.h" +#include "TestObj.h" +#include "WrapperTypeInfo.h" +#include <v8.h> +#include <wtf/HashMap.h> + +namespace WebCore { + +class V8TestObj { + +public: + static bool HasInstance(v8::Handle<v8::Value> value); + static v8::Persistent<v8::FunctionTemplate> GetRawTemplate(); + static v8::Persistent<v8::FunctionTemplate> GetTemplate(); + static TestObj* toNative(v8::Handle<v8::Object>); + static v8::Handle<v8::Object> wrap(TestObj*); + static void derefObject(void*); + static WrapperTypeInfo info; + static v8::Handle<v8::Value> customMethodCallback(const v8::Arguments&); + static v8::Handle<v8::Value> customMethodWithArgsCallback(const v8::Arguments&); + static v8::Handle<v8::Value> customAttrAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info); + static void customAttrAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info); + static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + 0; +}; + +v8::Handle<v8::Value> toV8(TestObj*); +v8::Handle<v8::Value> toV8(PassRefPtr<TestObj >); +} + +#endif // V8TestObj_h diff --git a/WebCore/bindings/v8/test/run_tests.py b/WebCore/bindings/v8/test/run_tests.py new file mode 100644 index 0000000..e27d559 --- /dev/null +++ b/WebCore/bindings/v8/test/run_tests.py @@ -0,0 +1,58 @@ +#!/usr/bin/python +# +# 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. +# + +# This script generates h and cpp file for TestObj.idl using the V8 code +# generator. Please execute the script whenever changes are made to +# CodeGeneratorV8.pm, and submit the changes in V8TestObj.h/cpp in the same +# patch. This makes it easier to track and review changes in generated code. +# To execute, invoke: 'python run_tests.py' + +import os +import sys + + +def test(idlFilePath): + cmd = ['perl', '-w', + '-I../../scripts', + '../../scripts/generate-bindings.pl', + # idl include directories (path relative to generate-bindings.pl) + '--include .', + # place holder for defines (generate-bindings.pl requires it) + '--defines xxx', + '--generator V8', + '--outputDir .', + idlFilePath] + os.system(' '.join(cmd)) + + +def main(argv): + scriptDir = os.path.dirname(__file__) + os.chdir(scriptDir) + test('TestObj.idl') + + +if __name__ == '__main__': + sys.exit(main(sys.argv)) |