diff options
Diffstat (limited to 'WebCore/bindings')
229 files changed, 6866 insertions, 6334 deletions
diff --git a/WebCore/bindings/ScriptControllerBase.cpp b/WebCore/bindings/ScriptControllerBase.cpp index 72c9f45..f1217e3 100644 --- a/WebCore/bindings/ScriptControllerBase.cpp +++ b/WebCore/bindings/ScriptControllerBase.cpp @@ -22,6 +22,7 @@ #include "ScriptController.h" #include "Frame.h" +#include "FrameLoaderClient.h" #include "Page.h" #include "ScriptSourceCode.h" #include "ScriptValue.h" @@ -30,6 +31,15 @@ namespace WebCore { +bool ScriptController::canExecuteScripts() +{ + if (m_frame->loader()->isSandboxed(SandboxScripts)) + return false; + + Settings* settings = m_frame->settings(); + return m_frame->loader()->client()->allowJavaScript(settings && settings->isJavaScriptEnabled()); +} + ScriptValue ScriptController::executeScript(const String& script, bool forceUserGesture) { return executeScript(ScriptSourceCode(script, forceUserGesture ? KURL() : m_frame->loader()->url())); @@ -37,7 +47,7 @@ ScriptValue ScriptController::executeScript(const String& script, bool forceUser ScriptValue ScriptController::executeScript(const ScriptSourceCode& sourceCode) { - if (!isEnabled() || isPaused()) + if (!canExecuteScripts() || isPaused()) return ScriptValue(); bool wasInExecuteScript = m_inExecuteScript; diff --git a/WebCore/bindings/generic/BindingDOMWindow.h b/WebCore/bindings/generic/BindingDOMWindow.h new file mode 100644 index 0000000..b968e2c --- /dev/null +++ b/WebCore/bindings/generic/BindingDOMWindow.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 BindingDOMWindow_h +#define BindingDOMWindow_h + +#include "Frame.h" +#include "FrameLoadRequest.h" +#include "GenericBinding.h" +#include "Page.h" + +namespace WebCore { + +template <class Binding> +class BindingDOMWindow { +public: + typedef typename Binding::Value BindingValue; + + static Frame* createWindow(State<Binding>*, + Frame* callingFrame, + Frame* enteredFrame, + Frame* openerFrame, + const String& url, + const String& frameName, + const WindowFeatures& windowFeatures, + BindingValue dialogArgs); +}; + +// Implementations of templated methods must be in this file. + +template <class Binding> +Frame* BindingDOMWindow<Binding>::createWindow(State<Binding>* state, + Frame* callingFrame, + Frame* enteredFrame, + Frame* openerFrame, + const String& url, + const String& frameName, + const WindowFeatures& windowFeatures, + BindingValue dialogArgs) +{ + ASSERT(callingFrame); + ASSERT(enteredFrame); + + // Sandboxed iframes cannot open new auxiliary browsing contexts. + if (callingFrame && callingFrame->loader()->isSandboxed(SandboxNavigation)) + return 0; + + ResourceRequest request; + + // For whatever reason, Firefox uses the entered frame to determine + // the outgoingReferrer. We replicate that behavior here. + String referrer = enteredFrame->loader()->outgoingReferrer(); + request.setHTTPReferrer(referrer); + FrameLoader::addHTTPOriginIfNeeded(request, enteredFrame->loader()->outgoingOrigin()); + FrameLoadRequest frameRequest(request, frameName); + + // FIXME: It's much better for client API if a new window starts with a URL, + // here where we know what URL we are going to open. Unfortunately, this + // code passes the empty string for the URL, but there's a reason for that. + // Before loading we have to set up the opener, openedByDOM, + // and dialogArguments values. Also, to decide whether to use the URL + // we currently do an allowsAccessFrom call using the window we create, + // which can't be done before creating it. We'd have to resolve all those + // issues to pass the URL instead of "". + + bool created; + // We pass in the opener frame here so it can be used for looking up the + // frame name, in case the active frame is different from the opener frame, + // and the name references a frame relative to the opener frame, for example + // "_self" or "_parent". + Frame* newFrame = callingFrame->loader()->createWindow(openerFrame->loader(), frameRequest, windowFeatures, created); + if (!newFrame) + return 0; + + newFrame->loader()->setOpener(openerFrame); + newFrame->page()->setOpenedByDOM(); + + Binding::DOMWindow::storeDialogArgs(state, newFrame, dialogArgs); + + if (!protocolIsJavaScript(url) || BindingSecurity<Binding>::canAccessFrame(state, newFrame, true)) { + KURL completedUrl = + url.isEmpty() ? KURL(ParsedURLString, "") : completeURL(url); + bool userGesture = processingUserGesture(); + + if (created) + newFrame->loader()->changeLocation(completedUrl, referrer, false, false, userGesture); + else if (!url.isEmpty()) + newFrame->redirectScheduler()->scheduleLocationChange(completedUrl.string(), referrer, false, userGesture); + } + + return newFrame; +} + +} // namespace WebCore + +#endif // BindingDOMWindow_h diff --git a/WebCore/bindings/generic/BindingSecurity.h b/WebCore/bindings/generic/BindingSecurity.h new file mode 100644 index 0000000..929b8f4 --- /dev/null +++ b/WebCore/bindings/generic/BindingSecurity.h @@ -0,0 +1,132 @@ +/* + * 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. + */ + +#ifndef BindingSecurity_h +#define BindingSecurity_h + +#include "BindingSecurityBase.h" +#include "CSSHelper.h" +#include "Element.h" +#include "GenericBinding.h" +#include "HTMLFrameElementBase.h" + +namespace WebCore { + +class DOMWindow; +class Frame; +class Node; + +// Security functions shared by various language bindings. +template <class Binding> +class BindingSecurity : public BindingSecurityBase { +public: + // Check if the active execution context can access the target frame. + static bool canAccessFrame(State<Binding>*, Frame*, bool reportError); + + // Check if it is safe to access the given node from the + // current security context. + static bool checkNodeSecurity(State<Binding>*, Node* target); + + static bool allowSettingFrameSrcToJavascriptUrl(State<Binding>*, HTMLFrameElementBase*, String value); + static bool allowSettingSrcToJavascriptURL(State<Binding>*, Element*, String name, String value); + +private: + explicit BindingSecurity() {} + ~BindingSecurity(); + + // Check if the current DOMWindow's security context can access the target + // DOMWindow. This function does not report errors, so most callers should + // use canAccessFrame instead. + static bool canAccessWindow(State<Binding>*, DOMWindow* target); +}; + +// Implementations of templated methods must be in this file. + +template <class Binding> +bool BindingSecurity<Binding>::canAccessWindow(State<Binding>* state, + DOMWindow* targetWindow) +{ + DOMWindow* activeWindow = state->getActiveWindow(); + return canAccess(activeWindow, targetWindow); +} + +template <class Binding> +bool BindingSecurity<Binding>::canAccessFrame(State<Binding>* state, + Frame* target, + bool reportError) +{ + // The subject is detached from a frame, deny accesses. + if (!target) + return false; + + if (!canAccessWindow(state, getDOMWindow(target))) { + if (reportError) + state->immediatelyReportUnsafeAccessTo(target); + return false; + } + return true; +} + +template <class Binding> +bool BindingSecurity<Binding>::checkNodeSecurity(State<Binding>* state, Node* node) +{ + if (!node) + return false; + + Frame* target = getFrame(node); + + if (!target) + return false; + + return canAccessFrame(state, target, true); +} + +template <class Binding> +bool BindingSecurity<Binding>::allowSettingFrameSrcToJavascriptUrl(State<Binding>* state, HTMLFrameElementBase* frame, String value) +{ + if (protocolIsJavaScript(deprecatedParseURL(value))) { + Node* contentDoc = frame->contentDocument(); + if (contentDoc && !checkNodeSecurity(state, contentDoc)) + return false; + } + return true; +} + +template <class Binding> +bool BindingSecurity<Binding>::allowSettingSrcToJavascriptURL(State<Binding>* state, Element* element, String name, String value) +{ + if ((element->hasTagName(HTMLNames::iframeTag) || element->hasTagName(HTMLNames::frameTag)) && equalIgnoringCase(name, "src")) + return allowSettingFrameSrcToJavascriptUrl(state, static_cast<HTMLFrameElementBase*>(element), value); + return true; +} + +} + +#endif // BindingSecurity_h diff --git a/WebCore/bindings/generic/BindingSecurityBase.cpp b/WebCore/bindings/generic/BindingSecurityBase.cpp new file mode 100644 index 0000000..1598781 --- /dev/null +++ b/WebCore/bindings/generic/BindingSecurityBase.cpp @@ -0,0 +1,108 @@ +/* + * 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 "BindingSecurityBase.h" + +#include "DOMWindow.h" +#include "Frame.h" +#include "SecurityOrigin.h" + +namespace WebCore { + +DOMWindow* BindingSecurityBase::getDOMWindow(Frame* frame) +{ + return frame->domWindow(); +} + +Frame* BindingSecurityBase::getFrame(Node* node) +{ + return node->document()->frame(); +} + +// Same origin policy implementation: +// +// Same origin policy prevents JS code from domain A from accessing JS & DOM +// objects in a different domain B. There are exceptions and several objects +// are accessible by cross-domain code. For example, the window.frames object +// is accessible by code from a different domain, but window.document is not. +// +// The JS binding code sets security check callbacks on a function template, +// and accessing instances of the template calls the callback function. +// The callback function enforces the same origin policy. +// +// Callback functions are expensive. Binding code should use a security token +// string to do fast access checks for the common case where source and target +// are in the same domain. A security token is a string object that represents +// the protocol/url/port of a domain. +// +// There are special cases where security token matching is not enough. +// For example, JS can set its domain to a super domain by calling +// document.setDomain(...). In these cases, the binding code can reset +// a context's security token to its global object so that the fast access +// check will always fail. + +// Helper to check if the current execution context can access a target frame. +// First it checks same domain policy using the lexical context. +// +// This is equivalent to KJS::Window::allowsAccessFrom(ExecState*). +bool BindingSecurityBase::canAccess(DOMWindow* activeWindow, + DOMWindow* targetWindow) +{ + ASSERT(targetWindow); + + String message; + + if (activeWindow == targetWindow) + return true; + + if (!activeWindow) + return false; + + const SecurityOrigin* activeSecurityOrigin = activeWindow->securityOrigin(); + const SecurityOrigin* targetSecurityOrigin = targetWindow->securityOrigin(); + + // We have seen crashes were the security origin of the target has not been + // initialized. Defend against that. + if (!targetSecurityOrigin) + return false; + + if (activeSecurityOrigin->canAccess(targetSecurityOrigin)) + return true; + + // Allow access to a "about:blank" page if the dynamic context is a + // detached context of the same frame as the blank page. + if (targetSecurityOrigin->isEmpty() && activeWindow->frame() == targetWindow->frame()) + return true; + + return false; +} + +} // namespace WebCore diff --git a/WebCore/bindings/generic/BindingSecurityBase.h b/WebCore/bindings/generic/BindingSecurityBase.h new file mode 100644 index 0000000..cfa2e99 --- /dev/null +++ b/WebCore/bindings/generic/BindingSecurityBase.h @@ -0,0 +1,52 @@ +/* + * 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. + */ + +#ifndef BindingSecurityBase_h +#define BindingSecurityBase_h + +namespace WebCore { + +class DOMWindow; +class Frame; +class Node; + +// Helper functions for BindingSecurity that depend on WebCore classes, and +// thus should not be implemented in BindingSecurity.h, which contains template +// method definitions. +class BindingSecurityBase { +protected: + static DOMWindow* getDOMWindow(Frame*); + static Frame* getFrame(Node*); + static bool canAccess(DOMWindow* active, DOMWindow* target); +}; + +} + +#endif // BindingSecurityBase_h diff --git a/WebCore/bindings/generic/GenericBinding.h b/WebCore/bindings/generic/GenericBinding.h new file mode 100644 index 0000000..d030b45 --- /dev/null +++ b/WebCore/bindings/generic/GenericBinding.h @@ -0,0 +1,52 @@ +/* + * 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. + */ + +#ifndef GenericBinding_h +#define GenericBinding_h + +namespace WebCore { + +// Used to instantiate binding templates for any methods shared among all +// language bindings. +class GenericBinding {}; + +// Class to represent execution state for each language binding. +template <class T> +class State {}; + +// Common notion of execution state for language bindings. +template <> +class State<GenericBinding> { + // Any methods shared across bindings can go here. +}; + +} + +#endif // GenericBinding_h diff --git a/WebCore/bindings/js/DOMObjectWithSVGContext.h b/WebCore/bindings/js/DOMObjectWithSVGContext.h deleted file mode 100644 index 3d435cb..0000000 --- a/WebCore/bindings/js/DOMObjectWithSVGContext.h +++ /dev/null @@ -1,57 +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: - * - * 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 THE AUTHOR ``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 AUTHOR 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 DOMObjectWithSVGContext_h -#define DOMObjectWithSVGContext_h - -#if ENABLE(SVG) - -#include "JSDOMBinding.h" -#include "SVGElement.h" - -namespace WebCore { - - // FIXME: This class (and file) should be removed once all SVG bindings - // have moved context() onto the various impl() pointers. - class DOMObjectWithSVGContext : public DOMObject { - public: - SVGElement* context() const { return m_context.get(); } - - protected: - DOMObjectWithSVGContext(NonNullPassRefPtr<JSC::Structure> structure, JSDOMGlobalObject*, SVGElement* context) - : DOMObject(structure) - , m_context(context) - { - // No space to store the JSDOMGlobalObject w/o hitting the CELL_SIZE limit. - } - - protected: // FIXME: Many custom bindings use m_context directly. Making this protected to temporariliy reduce code churn. - RefPtr<SVGElement> m_context; - }; - -} // namespace WebCore - -#endif // ENABLE(SVG) -#endif // DOMObjectWithSVGContext_h diff --git a/WebCore/bindings/js/GCController.cpp b/WebCore/bindings/js/GCController.cpp index 59bcfa3..3e5645f 100644 --- a/WebCore/bindings/js/GCController.cpp +++ b/WebCore/bindings/js/GCController.cpp @@ -40,17 +40,13 @@ using namespace JSC; namespace WebCore { -#if USE(PTHREADS) - static void* collect(void*) { JSLock lock(SilenceAssertionsOnly); - JSDOMWindow::commonJSGlobalData()->heap.collect(); + JSDOMWindow::commonJSGlobalData()->heap.collectAllGarbage(); return 0; } -#endif - GCController& gcController() { DEFINE_STATIC_LOCAL(GCController, staticGCController, ()); @@ -70,14 +66,12 @@ void GCController::garbageCollectSoon() void GCController::gcTimerFired(Timer<GCController>*) { - JSLock lock(SilenceAssertionsOnly); - JSDOMWindow::commonJSGlobalData()->heap.collect(); + collect(0); } void GCController::garbageCollectNow() { - JSLock lock(SilenceAssertionsOnly); - JSDOMWindow::commonJSGlobalData()->heap.collect(); + collect(0); } void GCController::garbageCollectOnAlternateThreadForDebugging(bool waitUntilDone) diff --git a/WebCore/bindings/js/JSBindingsAllInOne.cpp b/WebCore/bindings/js/JSBindingsAllInOne.cpp index cf1049a..e539042 100644 --- a/WebCore/bindings/js/JSBindingsAllInOne.cpp +++ b/WebCore/bindings/js/JSBindingsAllInOne.cpp @@ -86,7 +86,6 @@ #include "JSImageConstructor.cpp" #include "JSImageDataCustom.cpp" #include "JSInjectedScriptHostCustom.cpp" -#include "JSInspectedObjectWrapper.cpp" #include "JSInspectorFrontendHostCustom.cpp" #include "JSJavaScriptCallFrameCustom.cpp" #include "JSLazyEventListener.cpp" @@ -107,7 +106,6 @@ #include "JSPluginArrayCustom.cpp" #include "JSPluginCustom.cpp" #include "JSPluginElementFunctions.cpp" -#include "JSQuarantinedObjectWrapper.cpp" #include "JSSQLResultSetRowListCustom.cpp" #include "JSSQLTransactionCustom.cpp" #include "JSSVGElementInstanceCustom.cpp" @@ -115,7 +113,6 @@ #include "JSSVGMatrixCustom.cpp" #include "JSSVGPathSegCustom.cpp" #include "JSSVGPathSegListCustom.cpp" -#include "JSSVGPointListCustom.cpp" #include "JSSharedWorkerConstructor.cpp" #include "JSSharedWorkerCustom.cpp" #include "JSStorageCustom.cpp" diff --git a/WebCore/bindings/js/JSDOMBinding.cpp b/WebCore/bindings/js/JSDOMBinding.cpp index f12c779..04b6dc9 100644 --- a/WebCore/bindings/js/JSDOMBinding.cpp +++ b/WebCore/bindings/js/JSDOMBinding.cpp @@ -49,9 +49,11 @@ #include "ScriptController.h" #include "Settings.h" #include "XMLHttpRequestException.h" +#include <runtime/DateInstance.h> #include <runtime/Error.h> #include <runtime/JSFunction.h> #include <runtime/PrototypeFunction.h> +#include <wtf/MathExtras.h> #include <wtf/StdLibExtras.h> #if ENABLE(SVG) @@ -78,30 +80,32 @@ using namespace HTMLNames; typedef Document::JSWrapperCache JSWrapperCache; typedef Document::JSWrapperCacheMap JSWrapperCacheMap; -// For debugging, keep a set of wrappers currently registered, and check that -// all are unregistered before they are destroyed. This has helped us fix at -// least one bug. - -static void addWrapper(DOMObject* wrapper); -static void removeWrapper(DOMObject* wrapper); -static void removeWrappers(const JSWrapperCache& wrappers); -static void removeWrappers(const DOMObjectWrapperMap& wrappers); - -#ifdef NDEBUG - -static inline void addWrapper(DOMObject*) +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); } -static inline void removeWrapper(DOMObject*) -{ -} +// 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 removeWrappers(const JSWrapperCache&) +static inline void willCacheWrapper(DOMObject*) { } -static inline void removeWrappers(const DOMObjectWrapperMap&) +static inline void didUncacheWrapper(DOMObject*) { } @@ -118,13 +122,13 @@ static HashSet<DOMObject*>& wrapperSet() #endif } -static void addWrapper(DOMObject* wrapper) +static void willCacheWrapper(DOMObject* wrapper) { ASSERT(!wrapperSet().contains(wrapper)); wrapperSet().add(wrapper); } -static void removeWrapper(DOMObject* wrapper) +static void didUncacheWrapper(DOMObject* wrapper) { if (!wrapper) return; @@ -132,20 +136,6 @@ static void removeWrapper(DOMObject* wrapper) wrapperSet().remove(wrapper); } -static void removeWrappers(const JSWrapperCache& wrappers) -{ - JSWrapperCache::const_iterator wrappersEnd = wrappers.end(); - for (JSWrapperCache::const_iterator it = wrappers.begin(); it != wrappersEnd; ++it) - removeWrapper(it->second); -} - -static inline void removeWrappers(const DOMObjectWrapperMap& wrappers) -{ - DOMObjectWrapperMap::const_iterator wrappersEnd = wrappers.end(); - for (DOMObjectWrapperMap::const_iterator it = wrappers.begin(); it != wrappersEnd; ++it) - removeWrapper(it->second); -} - DOMObject::~DOMObject() { ASSERT(!wrapperSet().contains(this)); @@ -153,8 +143,9 @@ DOMObject::~DOMObject() #endif -DOMWrapperWorld::DOMWrapperWorld(JSC::JSGlobalData* globalData) +DOMWrapperWorld::DOMWrapperWorld(JSC::JSGlobalData* globalData, bool isNormal) : m_globalData(globalData) + , m_isNormal(isNormal) { } @@ -164,8 +155,6 @@ DOMWrapperWorld::~DOMWrapperWorld() ASSERT(clientData); static_cast<WebCoreJSClientData*>(clientData)->forgetWorld(this); - removeWrappers(m_wrappers); - for (HashSet<Document*>::iterator iter = documentsWithWrappers.begin(); iter != documentsWithWrappers.end(); ++iter) forgetWorldOfDOMNodesForDocument(*iter, this); } @@ -206,11 +195,6 @@ private: HashSet<DOMWrapperWorld*>::iterator m_end; }; -DOMWrapperWorld* currentWorld(JSC::ExecState* exec) -{ - return static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->world(); -} - DOMWrapperWorld* normalWorld(JSC::JSGlobalData& globalData) { JSGlobalData::ClientData* clientData = globalData.clientData; @@ -242,10 +226,19 @@ static inline DOMObjectWrapperMap& DOMObjectWrapperMapFor(JSC::ExecState* exec) return currentWorld(exec)->m_wrappers; } +bool hasCachedDOMObjectWrapperUnchecked(JSGlobalData* globalData, void* objectHandle) +{ + for (JSGlobalDataWorldIterator worldIter(globalData); worldIter; ++worldIter) { + if (worldIter->m_wrappers.uncheckedGet(objectHandle)) + return true; + } + return false; +} + bool hasCachedDOMObjectWrapper(JSGlobalData* globalData, void* objectHandle) { for (JSGlobalDataWorldIterator worldIter(globalData); worldIter; ++worldIter) { - if (worldIter->m_wrappers.contains(objectHandle)) + if (worldIter->m_wrappers.get(objectHandle)) return true; } return false; @@ -258,18 +251,18 @@ DOMObject* getCachedDOMObjectWrapper(JSC::ExecState* exec, void* objectHandle) void cacheDOMObjectWrapper(JSC::ExecState* exec, void* objectHandle, DOMObject* wrapper) { - addWrapper(wrapper); + willCacheWrapper(wrapper); DOMObjectWrapperMapFor(exec).set(objectHandle, wrapper); } -bool hasCachedDOMNodeWrapper(Document* document, Node* node) +bool hasCachedDOMNodeWrapperUnchecked(Document* document, Node* node) { if (!document) - return hasCachedDOMObjectWrapper(JSDOMWindow::commonJSGlobalData(), node); + return hasCachedDOMObjectWrapperUnchecked(JSDOMWindow::commonJSGlobalData(), node); JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap(); for (JSWrapperCacheMap::iterator iter = wrapperCacheMap.begin(); iter != wrapperCacheMap.end(); ++iter) { - if (iter->second->contains(node)) + if (iter->second->uncheckedGet(node)) return true; } return false; @@ -285,50 +278,50 @@ JSNode* getCachedDOMNodeWrapper(JSC::ExecState* exec, Document* document, Node* void forgetDOMObject(DOMObject* wrapper, void* objectHandle) { JSC::JSGlobalData* globalData = Heap::heap(wrapper)->globalData(); - for (JSGlobalDataWorldIterator worldIter(globalData); worldIter; ++worldIter) { - DOMObjectWrapperMap& wrappers = worldIter->m_wrappers; - DOMObjectWrapperMap::iterator iter = wrappers.find(objectHandle); - if ((iter != wrappers.end()) && (iter->second == wrapper)) { - removeWrapper(wrapper); - wrappers.remove(iter); - return; - } + + // Check the normal world first! + JSGlobalData::ClientData* clientData = globalData->clientData; + ASSERT(clientData); + DOMObjectWrapperMap& wrappers = static_cast<WebCoreJSClientData*>(clientData)->normalWorld()->m_wrappers; + if (wrappers.uncheckedRemove(objectHandle, wrapper)) { + didUncacheWrapper(wrapper); + return; } - // If the world went away, it should have removed this wrapper from the set. - ASSERT(!wrapperSet().contains(wrapper)); + // We can't guarantee that a wrapper is in the cache when it uncaches itself, + // since a new wrapper may be cached before the old wrapper's destructor runs. + for (JSGlobalDataWorldIterator worldIter(globalData); worldIter; ++worldIter) { + if (worldIter->m_wrappers.uncheckedRemove(objectHandle, wrapper)) + break; + } + didUncacheWrapper(wrapper); } -void forgetDOMNode(DOMObject* wrapper, Node* node, Document* document) +void forgetDOMNode(JSNode* wrapper, Node* node, Document* document) { if (!document) { forgetDOMObject(wrapper, node); return; } + // We can't guarantee that a wrapper is in the cache when it uncaches itself, + // since a new wrapper may be cached before the old wrapper's destructor runs. JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap(); for (JSWrapperCacheMap::iterator wrappersIter = wrapperCacheMap.begin(); wrappersIter != wrapperCacheMap.end(); ++wrappersIter) { - JSWrapperCache* wrappers = wrappersIter->second; - JSWrapperCache::iterator iter = wrappers->find(node); - if ((iter != wrappers->end()) && (iter->second == wrapper)) { - wrappers->remove(iter); - removeWrapper(wrapper); - return; - } + if (wrappersIter->second->uncheckedRemove(node, wrapper)) + break; } - - // If the world went away, it should have removed this wrapper from the set. - ASSERT(!wrapperSet().contains(wrapper)); + didUncacheWrapper(wrapper); } void cacheDOMNodeWrapper(JSC::ExecState* exec, Document* document, Node* node, JSNode* wrapper) { if (!document) { - addWrapper(wrapper); + willCacheWrapper(wrapper); DOMObjectWrapperMapFor(exec).set(node, wrapper); return; } - addWrapper(wrapper); + willCacheWrapper(wrapper); document->getWrapperCache(currentWorld(exec))->set(node, wrapper); } @@ -338,9 +331,7 @@ void forgetAllDOMNodesForDocument(Document* document) JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap(); JSWrapperCacheMap::const_iterator wrappersMapEnd = wrapperCacheMap.end(); for (JSWrapperCacheMap::const_iterator wrappersMapIter = wrapperCacheMap.begin(); wrappersMapIter != wrappersMapEnd; ++wrappersMapIter) { - JSWrapperCache* wrappers = wrappersMapIter->second; - removeWrappers(*wrappers); - delete wrappers; + delete wrappersMapIter->second; wrappersMapIter->first->forgetDocument(document); } } @@ -349,7 +340,6 @@ void forgetWorldOfDOMNodesForDocument(Document* document, DOMWrapperWorld* world { JSWrapperCache* wrappers = document->wrapperCacheMap().take(world); ASSERT(wrappers); // 'world' should only know about 'document' if 'document' knows about 'world'! - removeWrappers(*wrappers); delete wrappers; } @@ -379,14 +369,14 @@ static inline bool isObservableThroughDOM(JSNode* jsNode, DOMWrapperWorld* world // the custom markChildren functions rather than here. if (node->isElementNode()) { if (NamedNodeMap* attributes = static_cast<Element*>(node)->attributeMap()) { - if (DOMObject* wrapper = world->m_wrappers.get(attributes)) { + if (DOMObject* wrapper = world->m_wrappers.uncheckedGet(attributes)) { if (wrapper->hasCustomProperties()) return true; } } if (node->isStyledElement()) { if (CSSMutableStyleDeclaration* style = static_cast<StyledElement*>(node)->inlineStyleDecl()) { - if (DOMObject* wrapper = world->m_wrappers.get(style)) { + if (DOMObject* wrapper = world->m_wrappers.uncheckedGet(style)) { if (wrapper->hasCustomProperties()) return true; } @@ -394,7 +384,7 @@ static inline bool isObservableThroughDOM(JSNode* jsNode, DOMWrapperWorld* world } if (static_cast<Element*>(node)->hasTagName(canvasTag)) { if (CanvasRenderingContext* context = static_cast<HTMLCanvasElement*>(node)->renderingContext()) { - if (DOMObject* wrapper = world->m_wrappers.get(context)) { + if (DOMObject* wrapper = world->m_wrappers.uncheckedGet(context)) { if (wrapper->hasCustomProperties()) return true; } @@ -432,8 +422,8 @@ void markDOMNodesForDocument(MarkStack& markStack, Document* document) DOMWrapperWorld* world = wrappersIter->first; JSWrapperCache* nodeDict = wrappersIter->second; - JSWrapperCache::iterator nodeEnd = nodeDict->end(); - for (JSWrapperCache::iterator nodeIt = nodeDict->begin(); nodeIt != nodeEnd; ++nodeIt) { + JSWrapperCache::iterator nodeEnd = nodeDict->uncheckedEnd(); + for (JSWrapperCache::iterator nodeIt = nodeDict->uncheckedBegin(); nodeIt != nodeEnd; ++nodeIt) { JSNode* jsNode = nodeIt->second; if (isObservableThroughDOM(jsNode, world)) markStack.append(jsNode); @@ -451,8 +441,7 @@ void markActiveObjectsForContext(MarkStack& markStack, JSGlobalData& globalData, for (HashMap<ActiveDOMObject*, void*>::const_iterator iter = activeObjects.begin(); iter != activeObjectsEnd; ++iter) { if (iter->first->hasPendingActivity()) { // Generally, an active object with pending activity must have a wrapper to mark its listeners. - // However, some ActiveDOMObjects don't have JS wrappers (timers created by setTimeout is one example). - // FIXME: perhaps need to make sure even timers have a markable 'wrapper'. + // However, some ActiveDOMObjects don't have JS wrappers. markDOMObjectWrapper(markStack, globalData, iter->second); } } @@ -475,7 +464,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)) { - removeWrapper(wrapper); + didUncacheWrapper(wrapper); wrapperSet.append(WrapperAndWorld(wrapper, iter->first)); } } @@ -483,7 +472,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))) { - removeWrapper(wrapper); + didUncacheWrapper(wrapper); wrapperSet.append(WrapperAndWorld(wrapper, world)); } } @@ -499,11 +488,11 @@ void updateDOMNodeDocument(Node* node, Document* oldDocument, Document* newDocum for (unsigned i = 0; i < wrapperSet.size(); ++i) { JSNode* wrapper = wrapperSet[i].first; + willCacheWrapper(wrapper); if (newDocument) newDocument->getWrapperCache(wrapperSet[i].second)->set(node, wrapper); else wrapperSet[i].second->m_wrappers.set(node, wrapper); - addWrapper(wrapper); } } @@ -516,7 +505,7 @@ void markDOMObjectWrapper(MarkStack& markStack, JSGlobalData& globalData, void* return; for (JSGlobalDataWorldIterator worldIter(&globalData); worldIter; ++worldIter) { - if (DOMObject* wrapper = worldIter->m_wrappers.get(object)) + if (DOMObject* wrapper = worldIter->m_wrappers.uncheckedGet(object)) markStack.append(wrapper); } } @@ -526,18 +515,55 @@ void markDOMNodeWrapper(MarkStack& markStack, Document* document, Node* node) if (document) { JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap(); for (JSWrapperCacheMap::iterator iter = wrapperCacheMap.begin(); iter != wrapperCacheMap.end(); ++iter) { - if (JSNode* wrapper = iter->second->get(node)) + if (JSNode* wrapper = iter->second->uncheckedGet(node)) markStack.append(wrapper); } return; } for (JSGlobalDataWorldIterator worldIter(JSDOMWindow::commonJSGlobalData()); worldIter; ++worldIter) { - if (DOMObject* wrapper = worldIter->m_wrappers.get(node)) + if (DOMObject* wrapper = worldIter->m_wrappers.uncheckedGet(node)) markStack.append(wrapper); } } +static void stringWrapperDestroyed(JSString* str, void* context) +{ + StringImpl* cacheKey = static_cast<StringImpl*>(context); + JSC::JSGlobalData* globalData = Heap::heap(str)->globalData(); + + // Check the normal world first! + JSGlobalData::ClientData* clientData = globalData->clientData; + ASSERT(clientData); + JSStringCache& cache = static_cast<WebCoreJSClientData*>(clientData)->normalWorld()->m_stringCache; + if (cache.uncheckedRemove(cacheKey, str)) { + cacheKey->deref(); + return; + } + + for (JSGlobalDataWorldIterator worldIter(globalData); worldIter; ++worldIter) { + if (worldIter->m_stringCache.uncheckedRemove(cacheKey, str)) + break; + } + + cacheKey->deref(); +} + +JSValue jsStringSlowCase(ExecState* exec, JSStringCache& stringCache, StringImpl* stringImpl) +{ + // If there is a stale entry, we have to explicitly remove it to avoid + // problems down the line. + if (JSString* wrapper = stringCache.uncheckedGet(stringImpl)) + stringCache.uncheckedRemove(stringImpl, wrapper); + + JSString* wrapper = jsStringWithFinalizer(exec, stringImpl->ustring(), 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. + stringImpl->ref(); + return wrapper; +} + JSValue jsStringOrNull(ExecState* exec, const String& s) { if (s.isNull()) @@ -566,6 +592,11 @@ JSValue jsStringOrFalse(ExecState* exec, const String& s) return jsString(exec, s); } +JSValue jsString(ExecState* exec, const KURL& url) +{ + return jsString(exec, url.string()); +} + JSValue jsStringOrNull(ExecState* exec, const KURL& url) { if (url.isNull()) @@ -601,6 +632,22 @@ UString valueToStringWithUndefinedOrNullCheck(ExecState* exec, JSValue value) return value.toString(exec); } +JSValue jsDateOrNull(ExecState* exec, double value) +{ + if (!isfinite(value)) + return jsNull(); + return new (exec) DateInstance(exec, value); +} + +double valueToDate(ExecState* exec, JSValue value) +{ + if (value.isNumber()) + return value.uncheckedGetNumber(); + if (!value.inherits(&DateInstance::info)) + return std::numeric_limits<double>::quiet_NaN(); + return static_cast<DateInstance*>(value.toObject(exec))->internalNumber(); +} + void reportException(ExecState* exec, JSValue exception) { UString errorMessage = exception.toString(exec); @@ -659,7 +706,7 @@ void setDOMException(ExecState* exec, ExceptionCode ec) break; #if ENABLE(SVG) case SVGExceptionType: - errorObject = toJS(exec, globalObject, SVGException::create(description).get(), 0); + errorObject = toJS(exec, globalObject, SVGException::create(description).get(), 0 /* no context on purpose */); break; #endif #if ENABLE(XPATH) @@ -734,7 +781,7 @@ bool processingUserGesture(ExecState* exec) KURL completeURL(ExecState* exec, const String& relativeURL) { - // For histoical reasons, we need to complete the URL using the dynamic frame. + // For historical reasons, we need to complete the URL using the dynamic frame. Frame* frame = toDynamicFrame(exec); if (!frame) return KURL(); diff --git a/WebCore/bindings/js/JSDOMBinding.h b/WebCore/bindings/js/JSDOMBinding.h index 3982dad..5456c75 100644 --- a/WebCore/bindings/js/JSDOMBinding.h +++ b/WebCore/bindings/js/JSDOMBinding.h @@ -23,9 +23,11 @@ #define JSDOMBinding_h #include "JSDOMGlobalObject.h" -#include "Document.h" // For DOMConstructorWithDocument +#include "JSSVGContextCache.h" +#include "Document.h" #include <runtime/Completion.h> #include <runtime/Lookup.h> +#include <runtime/WeakGCMap.h> #include <wtf/Noncopyable.h> namespace JSC { @@ -69,41 +71,33 @@ namespace WebCore { // updated to store a globalObject pointer. class DOMObjectWithGlobalPointer : public DOMObject { public: - JSDOMGlobalObject* globalObject() const { return m_globalObject; } + JSDOMGlobalObject* globalObject() const { return static_cast<JSDOMGlobalObject*>(getAnonymousValue(GlobalObjectSlot).asCell()); } ScriptExecutionContext* scriptExecutionContext() const { // FIXME: Should never be 0, but can be due to bug 27640. - return m_globalObject->scriptExecutionContext(); + return globalObject()->scriptExecutionContext(); } static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) { - return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags)); + return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount); } protected: - static const unsigned StructureFlags = JSC::OverridesMarkChildren | DOMObject::StructureFlags; + static const unsigned AnonymousSlotCount = 1 + DOMObject::AnonymousSlotCount; + static const unsigned GlobalObjectSlot = AnonymousSlotCount - 1; DOMObjectWithGlobalPointer(NonNullPassRefPtr<JSC::Structure> structure, JSDOMGlobalObject* globalObject) : DOMObject(structure) - , m_globalObject(globalObject) { // FIXME: This ASSERT is valid, but fires in fast/dom/gc-6.html when trying to create // new JavaScript objects on detached windows due to DOMWindow::document() // needing to reach through the frame to get to the Document*. See bug 27640. // ASSERT(globalObject->scriptExecutionContext()); + putAnonymousValue(GlobalObjectSlot, globalObject); } virtual ~DOMObjectWithGlobalPointer() { } - - void markChildren(JSC::MarkStack& markStack) - { - DOMObject::markChildren(markStack); - markStack.append(m_globalObject); - } - - private: - JSDOMGlobalObject* m_globalObject; }; // Base class for all constructor objects in the JSC bindings. @@ -111,7 +105,7 @@ namespace WebCore { public: static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) { - return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags)); + return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount); } protected: @@ -139,11 +133,12 @@ namespace WebCore { } }; - typedef HashMap<void*, DOMObject*> DOMObjectWrapperMap; + typedef JSC::WeakGCMap<void*, DOMObject*> DOMObjectWrapperMap; + typedef JSC::WeakGCMap<StringImpl*, JSC::JSString*> JSStringCache; class DOMWrapperWorld : public RefCounted<DOMWrapperWorld> { public: - DOMWrapperWorld(JSC::JSGlobalData*); + DOMWrapperWorld(JSC::JSGlobalData*, bool isNormal); ~DOMWrapperWorld(); void rememberDocument(Document* document) { documentsWithWrappers.add(document); } @@ -151,10 +146,14 @@ namespace WebCore { // FIXME: can we make this private? DOMObjectWrapperMap m_wrappers; + JSStringCache m_stringCache; + + bool isNormal() const { return m_isNormal; } private: JSC::JSGlobalData* m_globalData; HashSet<Document*> documentsWithWrappers; + bool m_isNormal; }; // Map from static HashTable instances to per-GlobalData ones. @@ -181,12 +180,12 @@ namespace WebCore { HashMap<const JSC::HashTable*, JSC::HashTable> m_map; }; - class WebCoreJSClientData : public JSC::JSGlobalData::ClientData { + class WebCoreJSClientData : public JSC::JSGlobalData::ClientData, public Noncopyable { friend class JSGlobalDataWorldIterator; public: WebCoreJSClientData(JSC::JSGlobalData* globalData) - : m_normalWorld(globalData) + : m_normalWorld(globalData, true) { m_worldSet.add(&m_normalWorld); } @@ -216,22 +215,24 @@ namespace WebCore { DOMWrapperWorld m_normalWorld; }; - bool hasCachedDOMObjectWrapper(JSC::JSGlobalData*, void* objectHandle); DOMObject* getCachedDOMObjectWrapper(JSC::ExecState*, void* objectHandle); + bool hasCachedDOMObjectWrapper(JSC::JSGlobalData*, void* objectHandle); void cacheDOMObjectWrapper(JSC::ExecState*, void* objectHandle, DOMObject* wrapper); - void forgetDOMNode(DOMObject* wrapper, Node* node, Document* document); + void forgetDOMNode(JSNode* wrapper, Node* node, Document* document); void forgetDOMObject(DOMObject* wrapper, void* objectHandle); - bool hasCachedDOMNodeWrapper(Document*, Node*); 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*); void markActiveObjectsForContext(JSC::MarkStack&, JSC::JSGlobalData&, ScriptExecutionContext*); void markDOMObjectWrapper(JSC::MarkStack&, JSC::JSGlobalData& globalData, void* object); void markDOMNodeWrapper(JSC::MarkStack& markStack, Document* document, Node* node); + bool hasCachedDOMObjectWrapperUnchecked(JSC::JSGlobalData*, void* objectHandle); + bool hasCachedDOMNodeWrapperUnchecked(Document*, Node*); JSC::Structure* getCachedDOMStructure(JSDOMGlobalObject*, const JSC::ClassInfo*); JSC::Structure* cacheDOMStructure(JSDOMGlobalObject*, NonNullPassRefPtr<JSC::Structure>, const JSC::ClassInfo*); @@ -293,19 +294,21 @@ namespace WebCore { #define CREATE_SVG_OBJECT_WRAPPER(exec, globalObject, className, object, context) createDOMObjectWrapper<JS##className>(exec, globalObject, static_cast<className*>(object), context) template<class WrapperClass, class DOMClass> inline DOMObject* createDOMObjectWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* object, SVGElement* context) { - ASSERT(object); - ASSERT(!getCachedDOMObjectWrapper(exec, object)); - WrapperClass* wrapper = new (exec) WrapperClass(getDOMStructure<WrapperClass>(exec, globalObject), globalObject, object, context); - cacheDOMObjectWrapper(exec, object, wrapper); + DOMObject* wrapper = createDOMObjectWrapper<WrapperClass, DOMClass>(exec, globalObject, object); + ASSERT(wrapper); + if (context) + JSSVGContextCache::addWrapper(wrapper, context); return wrapper; } template<class WrapperClass, class DOMClass> inline JSC::JSValue getDOMObjectWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* object, SVGElement* context) { if (!object) return JSC::jsNull(); - if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec, object)) + if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec, object)) { + ASSERT(JSSVGContextCache::svgContextForDOMObject(wrapper) == context); return wrapper; - return createDOMObjectWrapper<WrapperClass>(exec, globalObject, object, context); + } + return createDOMObjectWrapper<WrapperClass, DOMClass>(exec, globalObject, object, context); } #endif @@ -337,6 +340,14 @@ namespace WebCore { // Convert a DOM implementation exception code into a JavaScript exception in the execution state. void setDOMException(JSC::ExecState*, ExceptionCode); + JSC::JSValue jsString(JSC::ExecState*, const String&); // empty if the string is null + JSC::JSValue jsStringSlowCase(JSC::ExecState*, JSStringCache&, StringImpl*); + JSC::JSValue jsString(JSC::ExecState*, const KURL&); // empty if the URL is null + inline JSC::JSValue jsString(JSC::ExecState* exec, const AtomicString& s) + { + return jsString(exec, s.string()); + } + JSC::JSValue jsStringOrNull(JSC::ExecState*, const String&); // null if the string is null JSC::JSValue jsStringOrNull(JSC::ExecState*, const KURL&); // null if the URL is null @@ -353,6 +364,11 @@ namespace WebCore { 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 + // Returns a Date instance for the specified value, or null if the value is NaN or infinity. + JSC::JSValue jsDateOrNull(JSC::ExecState*, double); + // NaN if the value can't be converted to a date. + double valueToDate(JSC::ExecState*, JSC::JSValue); + // FIXME: These are a stop-gap until all toJS calls can be converted to pass a globalObject template <typename T> inline JSC::JSValue toJS(JSC::ExecState* exec, T* ptr) @@ -395,6 +411,27 @@ namespace WebCore { 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) + { + StringImpl* stringImpl = s.impl(); + if (!stringImpl || !stringImpl->length()) + return jsEmptyString(exec); + + if (stringImpl->length() == 1 && stringImpl->characters()[0] <= 0xFF) + return jsString(exec, stringImpl->ustring()); + + JSStringCache& stringCache = currentWorld(exec)->m_stringCache; + if (JSC::JSString* wrapper = stringCache.get(stringImpl)) + return wrapper; + + return jsStringSlowCase(exec, stringCache, stringImpl); + } + } // namespace WebCore #endif // JSDOMBinding_h diff --git a/WebCore/bindings/js/JSDOMGlobalObject.cpp b/WebCore/bindings/js/JSDOMGlobalObject.cpp index 011a4e4..e0b5b89 100644 --- a/WebCore/bindings/js/JSDOMGlobalObject.cpp +++ b/WebCore/bindings/js/JSDOMGlobalObject.cpp @@ -40,6 +40,8 @@ using namespace JSC; namespace WebCore { +const ClassInfo JSDOMGlobalObject::s_info = { "DOMGlobalObject", 0, 0, 0 }; + JSDOMGlobalObject::JSDOMGlobalObject(NonNullPassRefPtr<Structure> structure, JSDOMGlobalObject::JSDOMGlobalObjectData* data, JSObject* thisValue) : JSGlobalObject(structure, data, thisValue) { @@ -56,14 +58,9 @@ void JSDOMGlobalObject::markChildren(MarkStack& markStack) JSDOMConstructorMap::iterator end2 = constructors().end(); for (JSDOMConstructorMap::iterator it2 = constructors().begin(); it2 != end2; ++it2) markStack.append(it2->second); -} -PassRefPtr<JSEventListener> JSDOMGlobalObject::createJSAttributeEventListener(JSValue val) -{ - if (!val.isObject()) - return 0; - - return JSEventListener::create(asObject(val), true, currentWorld(globalExec())).get(); + if (d()->m_injectedScript) + markStack.append(d()->m_injectedScript); } void JSDOMGlobalObject::setCurrentEvent(Event* evt) @@ -76,6 +73,16 @@ Event* JSDOMGlobalObject::currentEvent() const return d()->evt; } +void JSDOMGlobalObject::setInjectedScript(JSObject* injectedScript) +{ + d()->m_injectedScript = injectedScript; +} + +JSObject* JSDOMGlobalObject::injectedScript() const +{ + return d()->m_injectedScript; +} + void JSDOMGlobalObject::destroyJSDOMGlobalObjectData(void* jsDOMGlobalObjectData) { delete static_cast<JSDOMGlobalObjectData*>(jsDOMGlobalObjectData); diff --git a/WebCore/bindings/js/JSDOMGlobalObject.h b/WebCore/bindings/js/JSDOMGlobalObject.h index 647730c..8eb55c1 100644 --- a/WebCore/bindings/js/JSDOMGlobalObject.h +++ b/WebCore/bindings/js/JSDOMGlobalObject.h @@ -54,26 +54,29 @@ namespace WebCore { virtual ScriptExecutionContext* scriptExecutionContext() const = 0; - // Creates a JS EventListener for an "onXXX" event attribute. These - // listeners cannot be removed through the removeEventListener API. - PassRefPtr<JSEventListener> createJSAttributeEventListener(JSC::JSValue); - // Make binding code generation easier. JSDOMGlobalObject* globalObject() { return this; } void setCurrentEvent(Event*); Event* currentEvent() const; + void setInjectedScript(JSObject*); + JSObject* injectedScript() const; + virtual void markChildren(JSC::MarkStack&); DOMWrapperWorld* world() { return d()->m_world.get(); } + virtual const JSC::ClassInfo* classInfo() const { return &s_info; } + static const JSC::ClassInfo s_info; + protected: struct JSDOMGlobalObjectData : public JSC::JSGlobalObject::JSGlobalObjectData { JSDOMGlobalObjectData(DOMWrapperWorld* world, Destructor destructor = destroyJSDOMGlobalObjectData) : JSGlobalObjectData(destructor) , evt(0) , m_world(world) + , m_injectedScript(0) { } @@ -82,6 +85,7 @@ namespace WebCore { Event* evt; RefPtr<DOMWrapperWorld> m_world; + JSObject* m_injectedScript; }; private: diff --git a/WebCore/bindings/js/JSDOMWindowBase.cpp b/WebCore/bindings/js/JSDOMWindowBase.cpp index e3af13f..4338cdd 100644 --- a/WebCore/bindings/js/JSDOMWindowBase.cpp +++ b/WebCore/bindings/js/JSDOMWindowBase.cpp @@ -24,6 +24,7 @@ #include "JSDOMWindowBase.h" #include "CString.h" +#include "Chrome.h" #include "Console.h" #include "DOMWindow.h" #include "Frame.h" @@ -40,7 +41,7 @@ using namespace JSC; namespace WebCore { -const ClassInfo JSDOMWindowBase::s_info = { "Window", 0, 0, 0 }; +const ClassInfo JSDOMWindowBase::s_info = { "Window", &JSDOMGlobalObject::s_info, 0, 0 }; JSDOMWindowBase::JSDOMWindowBaseData::JSDOMWindowBaseData(PassRefPtr<DOMWindow> window, JSDOMWindowShell* shell) : JSDOMGlobalObjectData(shell->world(), destroyJSDOMWindowBaseData) @@ -75,7 +76,7 @@ ScriptExecutionContext* JSDOMWindowBase::scriptExecutionContext() const String JSDOMWindowBase::crossDomainAccessErrorMessage(const JSGlobalObject* other) const { KURL originURL = asJSDOMWindow(other)->impl()->url(); - KURL targetURL = impl()->frame()->document()->url(); + KURL targetURL = d()->shell->window()->impl()->url(); if (originURL.isNull() || targetURL.isNull()) return String(); @@ -170,7 +171,7 @@ void JSDOMWindowBase::destroyJSDOMWindowBaseData(void* jsDOMWindowBaseData) delete static_cast<JSDOMWindowBaseData*>(jsDOMWindowBaseData); } -// JSDOMGlobalObject* is ignored, accesing a window in any context will +// JSDOMGlobalObject* is ignored, accessing a window in any context will // use that DOMWindow's prototype chain. JSValue toJS(ExecState* exec, JSDOMGlobalObject*, DOMWindow* domWindow) { diff --git a/WebCore/bindings/js/JSDOMWindowBase.h b/WebCore/bindings/js/JSDOMWindowBase.h index 66af344..2726996 100644 --- a/WebCore/bindings/js/JSDOMWindowBase.h +++ b/WebCore/bindings/js/JSDOMWindowBase.h @@ -92,7 +92,7 @@ namespace WebCore { }; // Returns a JSDOMWindow or jsNull() - // JSDOMGlobalObject* is ignored, accesing a window in any context will + // JSDOMGlobalObject* is ignored, accessing a window in any context will // use that DOMWindow's prototype chain. JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, DOMWindow*); JSC::JSValue toJS(JSC::ExecState*, DOMWindow*); diff --git a/WebCore/bindings/js/JSDOMWindowCustom.cpp b/WebCore/bindings/js/JSDOMWindowCustom.cpp index 66fe926..1da5af2 100644 --- a/WebCore/bindings/js/JSDOMWindowCustom.cpp +++ b/WebCore/bindings/js/JSDOMWindowCustom.cpp @@ -22,6 +22,7 @@ #include "AtomicString.h" #include "Base64.h" +#include "Chrome.h" #include "DOMWindow.h" #include "Document.h" #include "ExceptionCode.h" @@ -112,6 +113,7 @@ void JSDOMWindow::markChildren(MarkStack& markStack) markDOMObjectWrapper(markStack, globalData, impl()->optionalStatusbar()); markDOMObjectWrapper(markStack, globalData, impl()->optionalToolbar()); markDOMObjectWrapper(markStack, globalData, impl()->optionalLocation()); + markDOMObjectWrapper(markStack, globalData, impl()->optionalMedia()); #if ENABLE(DOM_STORAGE) markDOMObjectWrapper(markStack, globalData, impl()->optionalSessionStorage()); markDOMObjectWrapper(markStack, globalData, impl()->optionalLocalStorage()); @@ -265,7 +267,7 @@ bool JSDOMWindow::getOwnPropertySlot(ExecState* exec, const Identifier& property } } - // FIXME: Search the whole frame hierachy somewhere around here. + // FIXME: Search the whole frame hierarchy somewhere around here. // We need to test the correct priority order. // allow window[1] or parent[1] etc. (#56983) @@ -323,22 +325,6 @@ bool JSDOMWindow::getOwnPropertyDescriptor(ExecState* exec, const Identifier& pr return true; } - // We need this code here because otherwise JSDOMWindowBase will stop the search before we even get to the - // prototype due to the blanket same origin (allowsAccessFrom) check at the end of getOwnPropertySlot. - // Also, it's important to get the implementation straight out of the DOMWindow prototype regardless of - // what prototype is actually set on this object. - entry = JSDOMWindowPrototype::s_info.propHashTable(exec)->entry(exec, propertyName); - if (entry) { - if (entry->attributes() & Function) { - if (entry->function() == jsDOMWindowPrototypeFunctionShowModalDialog) { - if (!DOMWindow::canShowModalDialog(impl()->frame())) { - descriptor.setUndefined(); - return true; - } - } - } - } - entry = JSDOMWindow::s_info.propHashTable(exec)->entry(exec, propertyName); if (entry) { PropertySlot slot; @@ -359,14 +345,6 @@ bool JSDOMWindow::getOwnPropertyDescriptor(ExecState* exec, const Identifier& pr return true; } - // Do prototype lookup early so that functions and attributes in the prototype can have - // precedence over the index and name getters. - JSValue proto = prototype(); - if (proto.isObject()) { - if (asObject(proto)->getPropertyDescriptor(exec, propertyName, descriptor)) - return true; - } - bool ok; unsigned i = propertyName.toArrayIndex(&ok); if (ok && i < impl()->frame()->tree()->childCount()) { @@ -418,20 +396,20 @@ bool JSDOMWindow::deleteProperty(ExecState* exec, const Identifier& propertyName return Base::deleteProperty(exec, propertyName); } -void JSDOMWindow::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSDOMWindow::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { // Only allow the window to enumerated by frames in the same origin. if (!allowsAccessFrom(exec)) return; - Base::getPropertyNames(exec, propertyNames); + Base::getPropertyNames(exec, propertyNames, mode); } -void JSDOMWindow::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSDOMWindow::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { // Only allow the window to enumerated by frames in the same origin. if (!allowsAccessFrom(exec)) return; - Base::getOwnPropertyNames(exec, propertyNames); + Base::getOwnPropertyNames(exec, propertyNames, mode); } void JSDOMWindow::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes) @@ -928,7 +906,12 @@ JSValue JSDOMWindow::setTimeout(ExecState* exec, const ArgList& args) if (exec->hadException()) return jsUndefined(); int delay = args.at(1).toInt32(exec); - return jsNumber(exec, impl()->setTimeout(action, delay)); + + ExceptionCode ec = 0; + int result = impl()->setTimeout(action, delay, ec); + setDOMException(exec, ec); + + return jsNumber(exec, result); } JSValue JSDOMWindow::setInterval(ExecState* exec, const ArgList& args) @@ -937,7 +920,12 @@ JSValue JSDOMWindow::setInterval(ExecState* exec, const ArgList& args) if (exec->hadException()) return jsUndefined(); int delay = args.at(1).toInt32(exec); - return jsNumber(exec, impl()->setInterval(action, delay)); + + ExceptionCode ec = 0; + int result = impl()->setInterval(action, delay, ec); + setDOMException(exec, ec); + + return jsNumber(exec, result); } JSValue JSDOMWindow::atob(ExecState* exec, const ArgList& args) diff --git a/WebCore/bindings/js/JSDOMWindowShell.cpp b/WebCore/bindings/js/JSDOMWindowShell.cpp index 09141ee..1e82a49 100644 --- a/WebCore/bindings/js/JSDOMWindowShell.cpp +++ b/WebCore/bindings/js/JSDOMWindowShell.cpp @@ -114,14 +114,14 @@ bool JSDOMWindowShell::deleteProperty(ExecState* exec, const Identifier& propert return m_window->deleteProperty(exec, propertyName); } -void JSDOMWindowShell::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSDOMWindowShell::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { - m_window->getPropertyNames(exec, propertyNames); + m_window->getPropertyNames(exec, propertyNames, mode); } -void JSDOMWindowShell::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSDOMWindowShell::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { - m_window->getOwnPropertyNames(exec, propertyNames); + m_window->getOwnPropertyNames(exec, propertyNames, mode); } void JSDOMWindowShell::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes) diff --git a/WebCore/bindings/js/JSDOMWindowShell.h b/WebCore/bindings/js/JSDOMWindowShell.h index 27036d4..1b986b8 100644 --- a/WebCore/bindings/js/JSDOMWindowShell.h +++ b/WebCore/bindings/js/JSDOMWindowShell.h @@ -60,7 +60,7 @@ namespace WebCore { static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) { - return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags)); + return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount); } DOMWrapperWorld* world() { return m_world.get(); } @@ -75,8 +75,8 @@ namespace WebCore { virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&); virtual void putWithAttributes(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, unsigned attributes); virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier& propertyName); - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); - virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); + virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties); + virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties); virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes); virtual void defineSetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction, unsigned attributes); virtual bool defineOwnProperty(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&, bool shouldThrow); diff --git a/WebCore/bindings/js/JSDocumentCustom.cpp b/WebCore/bindings/js/JSDocumentCustom.cpp index 4aa6583..9366399 100644 --- a/WebCore/bindings/js/JSDocumentCustom.cpp +++ b/WebCore/bindings/js/JSDocumentCustom.cpp @@ -96,18 +96,18 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, Document* documen if (!document) return jsNull(); - DOMObject* wrapper = getCachedDOMObjectWrapper(exec, document); + DOMObject* wrapper = getCachedDOMNodeWrapper(exec, document, document); if (wrapper) return wrapper; if (document->isHTMLDocument()) - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, HTMLDocument, document); + wrapper = CREATE_DOM_NODE_WRAPPER(exec, globalObject, HTMLDocument, document); #if ENABLE(SVG) else if (document->isSVGDocument()) - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, SVGDocument, document); + wrapper = CREATE_DOM_NODE_WRAPPER(exec, globalObject, SVGDocument, document); #endif else - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, Document, document); + wrapper = CREATE_DOM_NODE_WRAPPER(exec, globalObject, Document, document); // Make sure the document is kept around by the window object, and works right with the // back/forward cache. diff --git a/WebCore/bindings/js/JSEventListener.cpp b/WebCore/bindings/js/JSEventListener.cpp index 73060f1..d3b5fe1 100644 --- a/WebCore/bindings/js/JSEventListener.cpp +++ b/WebCore/bindings/js/JSEventListener.cpp @@ -81,7 +81,7 @@ void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext return; // FIXME: Is this check needed for other contexts? ScriptController* script = frame->script(); - if (!script->isEnabled() || script->isPaused()) + if (!script->canExecuteScripts() || script->isPaused()) return; } diff --git a/WebCore/bindings/js/JSEventListener.h b/WebCore/bindings/js/JSEventListener.h index bf3af48..9ba09c6 100644 --- a/WebCore/bindings/js/JSEventListener.h +++ b/WebCore/bindings/js/JSEventListener.h @@ -66,6 +66,16 @@ namespace WebCore { RefPtr<DOMWrapperWorld> m_isolatedWorld; }; + // Creates a JS EventListener for an "onXXX" event attribute. + inline PassRefPtr<JSEventListener> createJSAttributeEventListener(JSC::ExecState* exec, JSC::JSValue listener) + { + if (!listener.isObject()) + return 0; + + return JSEventListener::create(asObject(listener), true, currentWorld(exec)); + } + + } // namespace WebCore #endif // JSEventListener_h diff --git a/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp b/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp index 751e7de..80634f7 100644 --- a/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp +++ b/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp @@ -26,10 +26,12 @@ #include "config.h" #include "JSHTMLCanvasElement.h" +#include "CanvasContextAttributes.h" #include "HTMLCanvasElement.h" #include "JSCanvasRenderingContext2D.h" #if ENABLE(3D_CANVAS) #include "JSWebGLRenderingContext.h" +#include "WebGLContextAttributes.h" #endif #include <wtf/GetPtr.h> @@ -47,4 +49,36 @@ void JSHTMLCanvasElement::markChildren(MarkStack& markStack) markDOMObjectWrapper(markStack, globalData, canvas->renderingContext()); } +JSValue JSHTMLCanvasElement::getContext(ExecState* exec, const ArgList& args) +{ + HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(impl()); + const UString& contextId = args.at(0).toString(exec); + RefPtr<CanvasContextAttributes> attrs; +#if ENABLE(3D_CANVAS) + if (contextId == "experimental-webgl" || contextId == "webkit-3d") { + attrs = WebGLContextAttributes::create(); + WebGLContextAttributes* webGLAttrs = static_cast<WebGLContextAttributes*>(attrs.get()); + if (args.size() > 1 && args.at(1).isObject()) { + JSObject* jsAttrs = args.at(1).getObject(); + Identifier alpha(exec, "alpha"); + if (jsAttrs->hasProperty(exec, alpha)) + webGLAttrs->setAlpha(jsAttrs->get(exec, alpha).toBoolean(exec)); + Identifier depth(exec, "depth"); + if (jsAttrs->hasProperty(exec, depth)) + webGLAttrs->setDepth(jsAttrs->get(exec, depth).toBoolean(exec)); + Identifier stencil(exec, "stencil"); + if (jsAttrs->hasProperty(exec, stencil)) + webGLAttrs->setStencil(jsAttrs->get(exec, stencil).toBoolean(exec)); + Identifier antialias(exec, "antialias"); + if (jsAttrs->hasProperty(exec, antialias)) + webGLAttrs->setAntialias(jsAttrs->get(exec, antialias).toBoolean(exec)); + Identifier premultipliedAlpha(exec, "premultipliedAlpha"); + if (jsAttrs->hasProperty(exec, premultipliedAlpha)) + webGLAttrs->setPremultipliedAlpha(jsAttrs->get(exec, premultipliedAlpha).toBoolean(exec)); + } + } +#endif + return toJS(exec, globalObject(), WTF::getPtr(canvas->getContext(contextId, attrs.get()))); +} + } // namespace WebCore diff --git a/WebCore/bindings/js/JSHTMLFormElementCustom.cpp b/WebCore/bindings/js/JSHTMLFormElementCustom.cpp index de9ec4a..c364c14 100644 --- a/WebCore/bindings/js/JSHTMLFormElementCustom.cpp +++ b/WebCore/bindings/js/JSHTMLFormElementCustom.cpp @@ -66,7 +66,7 @@ JSValue JSHTMLFormElement::submit(ExecState* exec, const ArgList&) Frame* activeFrame = asJSDOMWindow(exec->dynamicGlobalObject())->impl()->frame(); if (!activeFrame) return jsUndefined(); - static_cast<HTMLFormElement*>(impl())->submit(0, false, !activeFrame->script()->anyPageIsProcessingUserGesture()); + static_cast<HTMLFormElement*>(impl())->submit(activeFrame); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSHistoryCustom.cpp b/WebCore/bindings/js/JSHistoryCustom.cpp index 3076503..fff747f 100644 --- a/WebCore/bindings/js/JSHistoryCustom.cpp +++ b/WebCore/bindings/js/JSHistoryCustom.cpp @@ -154,12 +154,12 @@ bool JSHistory::deleteProperty(ExecState* exec, const Identifier& propertyName) return Base::deleteProperty(exec, propertyName); } -void JSHistory::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSHistory::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { // Only allow the history object to enumerated by frames in the same origin. if (!allowsAccessFromFrame(exec, impl()->frame())) return; - Base::getOwnPropertyNames(exec, propertyNames); + Base::getOwnPropertyNames(exec, propertyNames, mode); } JSValue JSHistory::pushState(ExecState* exec, const ArgList& args) diff --git a/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp b/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp index fcc9e5e..d38d8ee 100644 --- a/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp +++ b/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp @@ -47,8 +47,6 @@ #include "InspectorController.h" #include "InspectorResource.h" #include "JSDOMWindow.h" -#include "JSInspectedObjectWrapper.h" -#include "JSInspectorCallbackWrapper.h" #include "JSNode.h" #include "JSRange.h" #include "Node.h" @@ -59,6 +57,7 @@ #endif #include "TextIterator.h" #include "VisiblePosition.h" +#include <parser/SourceCode.h> #include <runtime/JSArray.h> #include <runtime/JSLock.h> #include <wtf/Vector.h> @@ -73,6 +72,31 @@ using namespace JSC; namespace WebCore { +static ScriptObject createInjectedScript(const String& source, InjectedScriptHost* injectedScriptHost, ScriptState* scriptState, long id) +{ + SourceCode sourceCode = makeSource(source); + JSLock lock(SilenceAssertionsOnly); + JSDOMGlobalObject* globalObject = static_cast<JSDOMGlobalObject*>(scriptState->lexicalGlobalObject()); + JSValue globalThisValue = scriptState->globalThisValue(); + Completion comp = JSC::evaluate(scriptState, globalObject->globalScopeChain(), sourceCode, globalThisValue); + if (comp.complType() != JSC::Normal && comp.complType() != JSC::ReturnValue) + return ScriptObject(); + JSValue functionValue = comp.value(); + CallData callData; + CallType callType = functionValue.getCallData(callData); + if (callType == CallTypeNone) + return ScriptObject(); + + MarkedArgumentBuffer args; + args.append(toJS(scriptState, globalObject, injectedScriptHost)); + args.append(globalThisValue); + args.append(jsNumber(scriptState, id)); + JSValue result = JSC::call(scriptState, functionValue, callType, callData, globalThisValue, args); + if (result.isObject()) + return ScriptObject(scriptState, result.getObject()); + return ScriptObject(); +} + #if ENABLE(DATABASE) JSValue JSInjectedScriptHost::databaseForId(ExecState* exec, const ArgList& args) { @@ -86,29 +110,10 @@ JSValue JSInjectedScriptHost::databaseForId(ExecState* exec, const ArgList& args Database* database = impl()->databaseForId(args.at(0).toInt32(exec)); if (!database) return jsUndefined(); - // Could use currentWorld(exec) ... but which exec! The following mixed use of exec & inspectedWindow->globalExec() scares me! - JSDOMWindow* inspectedWindow = toJSDOMWindow(ic->inspectedPage()->mainFrame(), debuggerWorld()); - return JSInspectedObjectWrapper::wrap(inspectedWindow->globalExec(), toJS(exec, database)); + return toJS(exec, database); } #endif -JSValue JSInjectedScriptHost::inspectedWindow(ExecState*, const ArgList&) -{ - InspectorController* ic = impl()->inspectorController(); - if (!ic) - return jsUndefined(); - JSDOMWindow* inspectedWindow = toJSDOMWindow(ic->inspectedPage()->mainFrame(), debuggerWorld()); - return JSInspectedObjectWrapper::wrap(inspectedWindow->globalExec(), inspectedWindow); -} - -JSValue JSInjectedScriptHost::wrapCallback(ExecState* exec, const ArgList& args) -{ - if (args.size() < 1) - return jsUndefined(); - - return JSInspectorCallbackWrapper::wrap(exec, args.at(0)); -} - #if ENABLE(JAVASCRIPT_DEBUGGER) JSValue JSInjectedScriptHost::currentCallFrame(ExecState* exec, const ArgList&) @@ -117,11 +122,14 @@ JSValue JSInjectedScriptHost::currentCallFrame(ExecState* exec, const ArgList&) if (!callFrame || !callFrame->isValid()) return jsUndefined(); - // FIXME: I am not sure if this is actually needed. Can we just use exec? - ExecState* globalExec = callFrame->scopeChain()->globalObject->globalExec(); - JSLock lock(SilenceAssertionsOnly); - return JSInspectedObjectWrapper::wrap(globalExec, toJS(exec, callFrame)); + return toJS(exec, callFrame); +} + +JSValue JSInjectedScriptHost::isActivation(ExecState*, const ArgList& args) +{ + JSObject* object = args.at(0).getObject(); + return jsBoolean(object && object->isActivationObject()); } #endif @@ -140,41 +148,21 @@ JSValue JSInjectedScriptHost::nodeForId(ExecState* exec, const ArgList& args) return jsUndefined(); JSLock lock(SilenceAssertionsOnly); - JSDOMWindow* inspectedWindow = toJSDOMWindow(ic->inspectedPage()->mainFrame(), debuggerWorld()); - return JSInspectedObjectWrapper::wrap(inspectedWindow->globalExec(), toJS(exec, deprecatedGlobalObjectForPrototype(inspectedWindow->globalExec()), node)); -} - -JSValue JSInjectedScriptHost::wrapObject(ExecState* exec, const ArgList& args) -{ - if (args.size() < 2) - return jsUndefined(); - - return impl()->wrapObject(ScriptValue(args.at(0)), args.at(1).toString(exec)).jsValue(); -} - -JSValue JSInjectedScriptHost::unwrapObject(ExecState* exec, const ArgList& args) -{ - if (args.size() < 1) - return jsUndefined(); - - return impl()->unwrapObject(args.at(0).toString(exec)).jsValue(); + return toJS(exec, node); } JSValue JSInjectedScriptHost::pushNodePathToFrontend(ExecState* exec, const ArgList& args) { - if (args.size() < 2) + if (args.size() < 3) return jsUndefined(); - JSQuarantinedObjectWrapper* wrapper = JSQuarantinedObjectWrapper::asWrapper(args.at(0)); - if (!wrapper) - return jsUndefined(); - - Node* node = toNode(wrapper->unwrappedObject()); + Node* node = toNode(args.at(0)); if (!node) return jsUndefined(); - bool selectInUI = args.at(1).toBoolean(exec); - return jsNumber(exec, impl()->pushNodePathToFrontend(node, selectInUI)); + bool withChildren = args.at(1).toBoolean(exec); + bool selectInUI = args.at(2).toBoolean(exec); + return jsNumber(exec, impl()->pushNodePathToFrontend(node, withChildren, selectInUI)); } #if ENABLE(DATABASE) @@ -183,11 +171,7 @@ JSValue JSInjectedScriptHost::selectDatabase(ExecState*, const ArgList& args) if (args.size() < 1) return jsUndefined(); - JSQuarantinedObjectWrapper* wrapper = JSQuarantinedObjectWrapper::asWrapper(args.at(0)); - if (!wrapper) - return jsUndefined(); - - Database* database = toDatabase(wrapper->unwrappedObject()); + Database* database = toDatabase(args.at(0)); if (database) impl()->selectDatabase(database); return jsUndefined(); @@ -203,17 +187,29 @@ JSValue JSInjectedScriptHost::selectDOMStorage(ExecState*, const ArgList& args) if (!ic) return jsUndefined(); - JSQuarantinedObjectWrapper* wrapper = JSQuarantinedObjectWrapper::asWrapper(args.at(0)); - if (!wrapper) - return jsUndefined(); - - Storage* storage = toStorage(wrapper->unwrappedObject()); + Storage* storage = toStorage(args.at(0)); if (storage) impl()->selectDOMStorage(storage); return jsUndefined(); } #endif +ScriptObject InjectedScriptHost::injectedScriptFor(ScriptState* scriptState) +{ + JSLock lock(SilenceAssertionsOnly); + JSDOMGlobalObject* globalObject = static_cast<JSDOMGlobalObject*>(scriptState->lexicalGlobalObject()); + JSObject* injectedScript = globalObject->injectedScript(); + if (injectedScript) + return ScriptObject(scriptState, injectedScript); + + ASSERT(!m_injectedScriptSource.isEmpty()); + ScriptObject injectedScriptObject = createInjectedScript(m_injectedScriptSource, this, scriptState, m_nextInjectedScriptId); + globalObject->setInjectedScript(injectedScriptObject.jsObject()); + m_idToInjectedScript.set(m_nextInjectedScriptId, injectedScriptObject); + m_nextInjectedScriptId++; + return injectedScriptObject; +} + } // namespace WebCore #endif // ENABLE(INSPECTOR) diff --git a/WebCore/bindings/js/JSInspectedObjectWrapper.cpp b/WebCore/bindings/js/JSInspectedObjectWrapper.cpp deleted file mode 100644 index 13f59b7..0000000 --- a/WebCore/bindings/js/JSInspectedObjectWrapper.cpp +++ /dev/null @@ -1,132 +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 "JSInspectedObjectWrapper.h" - -#if ENABLE(INSPECTOR) - -#include "JSInspectorCallbackWrapper.h" -#include <runtime/JSGlobalObject.h> -#include <wtf/StdLibExtras.h> - -using namespace JSC; - -namespace WebCore { - -ASSERT_CLASS_FITS_IN_CELL(JSInspectedObjectWrapper); - -typedef HashMap<JSObject*, JSInspectedObjectWrapper*> WrapperMap; -typedef HashMap<JSGlobalObject*, WrapperMap*> GlobalObjectWrapperMap; - -static GlobalObjectWrapperMap& wrappers() -{ - DEFINE_STATIC_LOCAL(GlobalObjectWrapperMap, map, ()); - return map; -} - -const ClassInfo JSInspectedObjectWrapper::s_info = { "JSInspectedObjectWrapper", &JSQuarantinedObjectWrapper::s_info, 0, 0 }; - -JSValue JSInspectedObjectWrapper::wrap(ExecState* unwrappedExec, JSValue unwrappedValue) -{ - if (!unwrappedValue.isObject()) - return unwrappedValue; - - JSObject* unwrappedObject = asObject(unwrappedValue); - - if (unwrappedObject->inherits(&JSInspectedObjectWrapper::s_info)) - return unwrappedObject; - - if (WrapperMap* wrapperMap = wrappers().get(unwrappedExec->lexicalGlobalObject())) - if (JSInspectedObjectWrapper* wrapper = wrapperMap->get(unwrappedObject)) - return wrapper; - - JSValue prototype = unwrappedObject->prototype(); - ASSERT(prototype.isNull() || prototype.isObject()); - - if (prototype.isNull()) - return new (unwrappedExec) JSInspectedObjectWrapper(unwrappedExec, unwrappedObject, JSQuarantinedObjectWrapper::createStructure(jsNull())); - ProtectedJSValue wrappedProto = wrap(unwrappedExec, prototype); - return new (unwrappedExec) JSInspectedObjectWrapper(unwrappedExec, unwrappedObject, JSQuarantinedObjectWrapper::createStructure(asObject(wrappedProto))); -} - -JSInspectedObjectWrapper::JSInspectedObjectWrapper(ExecState* unwrappedExec, JSObject* unwrappedObject, NonNullPassRefPtr<Structure> structure) - : JSQuarantinedObjectWrapper(unwrappedExec, unwrappedObject, structure) -{ - WrapperMap* wrapperMap = wrappers().get(unwrappedGlobalObject()); - if (!wrapperMap) { - wrapperMap = new WrapperMap; - wrappers().set(unwrappedGlobalObject(), wrapperMap); - } - - ASSERT(!wrapperMap->contains(unwrappedObject)); - wrapperMap->set(unwrappedObject, this); -} - -JSInspectedObjectWrapper::~JSInspectedObjectWrapper() -{ - ASSERT(wrappers().contains(unwrappedGlobalObject())); - WrapperMap* wrapperMap = wrappers().get(unwrappedGlobalObject()); - - ASSERT(wrapperMap->contains(unwrappedObject())); - wrapperMap->remove(unwrappedObject()); - - if (wrapperMap->isEmpty()) { - wrappers().remove(unwrappedGlobalObject()); - delete wrapperMap; - } -} - -JSValue JSInspectedObjectWrapper::prepareIncomingValue(ExecState*, JSValue value) const -{ - // The Inspector is only allowed to pass primitive values and wrapped objects to objects from the inspected page. - - if (!value.isObject()) - return value; - - JSQuarantinedObjectWrapper* wrapper = asWrapper(value); - ASSERT_WITH_MESSAGE(wrapper, "Objects passed to JSInspectedObjectWrapper must be wrapped"); - if (!wrapper) - return jsUndefined(); - - if (wrapper->allowsUnwrappedAccessFrom(unwrappedExecState())) { - ASSERT_WITH_MESSAGE(wrapper->inherits(&s_info), "A wrapper contains an object from the inspected page but is not a JSInspectedObjectWrapper"); - if (!wrapper->inherits(&s_info)) - return jsUndefined(); - - // Return the unwrapped object so the inspected page never sees one of its own objects in wrapped form. - return wrapper->unwrappedObject(); - } - - ASSERT_WITH_MESSAGE(wrapper->inherits(&JSInspectorCallbackWrapper::s_info), "A wrapper that was not from the inspected page and is not an Inspector callback was passed to a JSInspectedObjectWrapper"); - if (!wrapper->inherits(&JSInspectorCallbackWrapper::s_info)) - return jsUndefined(); - - return wrapper; -} - -} // namespace WebCore - -#endif // ENABLE(INSPECTOR) diff --git a/WebCore/bindings/js/JSInspectedObjectWrapper.h b/WebCore/bindings/js/JSInspectedObjectWrapper.h deleted file mode 100644 index ad97035..0000000 --- a/WebCore/bindings/js/JSInspectedObjectWrapper.h +++ /dev/null @@ -1,59 +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. - */ - -#ifndef JSInspectedObjectWrapper_h -#define JSInspectedObjectWrapper_h - -#include "JSQuarantinedObjectWrapper.h" - -namespace WebCore { - - class JSInspectedObjectWrapper : public JSQuarantinedObjectWrapper { - public: - static JSC::JSValue wrap(JSC::ExecState* unwrappedExec, JSC::JSValue unwrappedValue); - virtual ~JSInspectedObjectWrapper(); - - static const JSC::ClassInfo s_info; - - private: - JSInspectedObjectWrapper(JSC::ExecState* unwrappedExec, JSC::JSObject* unwrappedObject, NonNullPassRefPtr<JSC::Structure>); - - virtual bool allowsGetProperty() const { return true; } - virtual bool allowsSetProperty() const { return true; } - virtual bool allowsDeleteProperty() const { return true; } - virtual bool allowsConstruct() const { return true; } - virtual bool allowsHasInstance() const { return true; } - virtual bool allowsCallAsFunction() const { return true; } - virtual bool allowsGetPropertyNames() const { return true; } - - virtual JSC::JSValue prepareIncomingValue(JSC::ExecState* unwrappedExec, JSC::JSValue unwrappedValue) const; - virtual JSC::JSValue wrapOutgoingValue(JSC::ExecState* unwrappedExec, JSC::JSValue unwrappedValue) const { return wrap(unwrappedExec, unwrappedValue); } - - virtual const JSC::ClassInfo* classInfo() const { return &s_info; } - }; - -} // namespace WebCore - -#endif // JSInspectedObjectWrapper_h diff --git a/WebCore/bindings/js/JSInspectorCallbackWrapper.cpp b/WebCore/bindings/js/JSInspectorCallbackWrapper.cpp deleted file mode 100644 index ff4fbb9..0000000 --- a/WebCore/bindings/js/JSInspectorCallbackWrapper.cpp +++ /dev/null @@ -1,112 +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 "JSInspectorCallbackWrapper.h" - -#if ENABLE(INSPECTOR) - -#include "JSInspectedObjectWrapper.h" -#include <wtf/StdLibExtras.h> - -using namespace JSC; - -namespace WebCore { - -ASSERT_CLASS_FITS_IN_CELL(JSInspectorCallbackWrapper); - -typedef HashMap<JSObject*, JSInspectorCallbackWrapper*> WrapperMap; - -static WrapperMap& wrappers() -{ - DEFINE_STATIC_LOCAL(WrapperMap, map, ()); - return map; -} - -const ClassInfo JSInspectorCallbackWrapper::s_info = { "JSInspectorCallbackWrapper", &JSQuarantinedObjectWrapper::s_info, 0, 0 }; - -static Structure* leakInspectorCallbackWrapperStructure() -{ - Structure::startIgnoringLeaks(); - Structure* structure = JSInspectorCallbackWrapper::createStructure(jsNull()).releaseRef(); - Structure::stopIgnoringLeaks(); - return structure; -} - -JSValue JSInspectorCallbackWrapper::wrap(ExecState* unwrappedExec, JSValue unwrappedValue) -{ - if (!unwrappedValue.isObject()) - return unwrappedValue; - - JSObject* unwrappedObject = asObject(unwrappedValue); - - if (unwrappedObject->inherits(&JSInspectorCallbackWrapper::s_info)) - return unwrappedObject; - - if (JSInspectorCallbackWrapper* wrapper = wrappers().get(unwrappedObject)) - return wrapper; - - JSValue prototype = unwrappedObject->prototype(); - ASSERT(prototype.isNull() || prototype.isObject()); - - if (prototype.isNull()) { - static Structure* structure = leakInspectorCallbackWrapperStructure(); - return new (unwrappedExec) JSInspectorCallbackWrapper(unwrappedExec, unwrappedObject, structure); - } - ProtectedJSValue wrappedProto = wrap(unwrappedExec, prototype); - return new (unwrappedExec) JSInspectorCallbackWrapper(unwrappedExec, unwrappedObject, createStructure(wrappedProto.get())); -} - -JSInspectorCallbackWrapper::JSInspectorCallbackWrapper(ExecState* unwrappedExec, JSObject* unwrappedObject, NonNullPassRefPtr<Structure> structure) - : JSQuarantinedObjectWrapper(unwrappedExec, unwrappedObject, structure) -{ - ASSERT(!wrappers().contains(unwrappedObject)); - wrappers().set(unwrappedObject, this); -} - -JSInspectorCallbackWrapper::~JSInspectorCallbackWrapper() -{ - wrappers().remove(unwrappedObject()); -} - -JSValue JSInspectorCallbackWrapper::prepareIncomingValue(ExecState* unwrappedExec, JSValue unwrappedValue) const -{ - if (JSQuarantinedObjectWrapper* wrapper = asWrapper(unwrappedValue)) { - // The only time a wrapper should be passed into a JSInspectorCallbackWrapper is when a client-side storage callback - // is called. (The client-side storage API calls the callback with the `this` object set to the callback itself.) - ASSERT_WITH_MESSAGE(wrapper == this, "A different wrapper was passed into a JSInspectorCallbackWrapper"); - if (wrapper != this) - return jsUndefined(); - - return wrapper->unwrappedObject(); - } - - // Any value being passed to the Inspector from the inspected page should be wrapped in a JSInspectedObjectWrapper. - return JSInspectedObjectWrapper::wrap(unwrappedExec, unwrappedValue); -} - -} // namespace WebCore - -#endif // ENABLE(INSPECTOR) diff --git a/WebCore/bindings/js/JSInspectorCallbackWrapper.h b/WebCore/bindings/js/JSInspectorCallbackWrapper.h deleted file mode 100644 index be28063..0000000 --- a/WebCore/bindings/js/JSInspectorCallbackWrapper.h +++ /dev/null @@ -1,53 +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. - */ - -#ifndef JSInspectorCallbackWrapper_h -#define JSInspectorCallbackWrapper_h - -#include "JSQuarantinedObjectWrapper.h" - -namespace WebCore { - - class JSInspectorCallbackWrapper : public JSQuarantinedObjectWrapper { - public: - static JSC::JSValue wrap(JSC::ExecState* unwrappedExec, JSC::JSValue unwrappedValue); - - virtual ~JSInspectorCallbackWrapper(); - - virtual const JSC::ClassInfo* classInfo() const { return &s_info; } - static const JSC::ClassInfo s_info; - - protected: - JSInspectorCallbackWrapper(JSC::ExecState* unwrappedExec, JSC::JSObject* unwrappedObject, NonNullPassRefPtr<JSC::Structure>); - - virtual bool allowsCallAsFunction() const { return true; } - - virtual JSC::JSValue prepareIncomingValue(JSC::ExecState* unwrappedExec, JSC::JSValue unwrappedValue) const; - virtual JSC::JSValue wrapOutgoingValue(JSC::ExecState* unwrappedExec, JSC::JSValue unwrappedValue) const { return wrap(unwrappedExec, unwrappedValue); } - }; - -} // namespace WebCore - -#endif // JSInspectorCallbackWrapper_h diff --git a/WebCore/bindings/js/JSInspectorFrontendHostCustom.cpp b/WebCore/bindings/js/JSInspectorFrontendHostCustom.cpp index 1970bf7..7b06bac 100644 --- a/WebCore/bindings/js/JSInspectorFrontendHostCustom.cpp +++ b/WebCore/bindings/js/JSInspectorFrontendHostCustom.cpp @@ -36,18 +36,10 @@ #if ENABLE(INSPECTOR) #include "ContextMenuItem.h" -#include "ExceptionCode.h" -#include "Frame.h" #include "InspectorController.h" #include "InspectorFrontendHost.h" #include "JSEvent.h" -#include "JSNode.h" -#include "JSRange.h" #include "MouseEvent.h" -#include "Node.h" -#include "Page.h" -#include "TextIterator.h" -#include "VisiblePosition.h" #include <runtime/JSArray.h> #include <runtime/JSLock.h> #include <runtime/JSObject.h> @@ -57,42 +49,6 @@ using namespace JSC; namespace WebCore { -JSValue JSInspectorFrontendHost::search(ExecState* exec, const ArgList& args) -{ - if (args.size() < 2) - return jsUndefined(); - - Node* node = toNode(args.at(0)); - if (!node) - return jsUndefined(); - - String target = args.at(1).toString(exec); - if (exec->hadException()) - return jsUndefined(); - - MarkedArgumentBuffer result; - RefPtr<Range> searchRange(rangeOfContents(node)); - - ExceptionCode ec = 0; - do { - RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, true, false)); - if (resultRange->collapsed(ec)) - break; - - // A non-collapsed result range can in some funky whitespace cases still not - // advance the range's start position (4509328). Break to avoid infinite loop. - VisiblePosition newStart = endVisiblePosition(resultRange.get(), DOWNSTREAM); - if (newStart == startVisiblePosition(searchRange.get(), DOWNSTREAM)) - break; - - result.append(toJS(exec, resultRange.get())); - - setStart(searchRange.get(), newStart); - } while (true); - - return constructArray(exec, result); -} - JSValue JSInspectorFrontendHost::showContextMenu(ExecState* execState, const ArgList& args) { if (args.size() < 2) @@ -101,17 +57,17 @@ JSValue JSInspectorFrontendHost::showContextMenu(ExecState* execState, const Arg Event* event = toEvent(args.at(0)); JSArray* array = asArray(args.at(1)); - Vector<ContextMenuItem> items; + Vector<ContextMenuItem*> items; for (size_t i = 0; i < array->length(); ++i) { JSObject* item = asObject(array->getIndex(i)); JSValue label = item->get(execState, Identifier(execState, "label")); JSValue id = item->get(execState, Identifier(execState, "id")); if (label.isUndefined() || id.isUndefined()) - items.append(ContextMenuItem(SeparatorType, ContextMenuItemTagNoAction, String())); + items.append(new ContextMenuItem(SeparatorType, ContextMenuItemTagNoAction, String())); else { ContextMenuAction typedId = static_cast<ContextMenuAction>(ContextMenuItemBaseCustomTag + id.toInt32(execState)); - items.append(ContextMenuItem(ActionType, typedId, label.toString(execState))); + items.append(new ContextMenuItem(ActionType, typedId, label.toString(execState))); } } diff --git a/WebCore/bindings/js/JSJavaScriptCallFrameCustom.cpp b/WebCore/bindings/js/JSJavaScriptCallFrameCustom.cpp index 08ecf2b..afbdf5d 100644 --- a/WebCore/bindings/js/JSJavaScriptCallFrameCustom.cpp +++ b/WebCore/bindings/js/JSJavaScriptCallFrameCustom.cpp @@ -55,9 +55,9 @@ JSValue JSJavaScriptCallFrame::type(ExecState* exec) const { switch (impl()->type()) { case DebuggerCallFrame::FunctionType: - return jsString(exec, "function"); + return jsString(exec, UString("function")); case DebuggerCallFrame::ProgramType: - return jsString(exec, "program"); + return jsString(exec, UString("program")); } ASSERT_NOT_REACHED(); diff --git a/WebCore/bindings/js/JSLazyEventListener.cpp b/WebCore/bindings/js/JSLazyEventListener.cpp index 6d75f4f..b707991 100644 --- a/WebCore/bindings/js/JSLazyEventListener.cpp +++ b/WebCore/bindings/js/JSLazyEventListener.cpp @@ -89,7 +89,7 @@ void JSLazyEventListener::parseCode(ScriptExecutionContext* executionContext) co return; ScriptController* scriptController = frame->script(); - if (!scriptController->isEnabled()) + if (!scriptController->canExecuteScripts()) return; JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(executionContext, m_isolatedWorld.get()); @@ -110,7 +110,7 @@ void JSLazyEventListener::parseCode(ScriptExecutionContext* executionContext) co return; // FIXME: Is this check needed for non-Document contexts? ScriptController* script = frame->script(); - if (!script->isEnabled() || script->isPaused()) + if (!script->canExecuteScripts() || script->isPaused()) return; } diff --git a/WebCore/bindings/js/JSLocationCustom.cpp b/WebCore/bindings/js/JSLocationCustom.cpp index 6c8e032..8599242 100644 --- a/WebCore/bindings/js/JSLocationCustom.cpp +++ b/WebCore/bindings/js/JSLocationCustom.cpp @@ -24,6 +24,7 @@ #include "JSLocationCustom.h" #include "DOMWindow.h" +#include "ExceptionCode.h" #include "Frame.h" #include "FrameLoader.h" #include "JSDOMBinding.h" @@ -168,12 +169,12 @@ bool JSLocation::deleteProperty(ExecState* exec, const Identifier& propertyName) return Base::deleteProperty(exec, propertyName); } -void JSLocation::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSLocation::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { // Only allow the location object to enumerated by frames in the same origin. if (!allowsAccessFromFrame(exec, impl()->frame())) return; - Base::getOwnPropertyNames(exec, propertyNames); + Base::getOwnPropertyNames(exec, propertyNames, mode); } void JSLocation::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes) @@ -214,7 +215,10 @@ void JSLocation::setProtocol(ExecState* exec, JSValue value) ASSERT(frame); KURL url = frame->loader()->url(); - url.setProtocol(value.toString(exec)); + if (!url.setProtocol(value.toString(exec))) { + setDOMException(exec, SYNTAX_ERR); + return; + } navigateIfAllowed(exec, frame, url, !frame->script()->anyPageIsProcessingUserGesture(), false); } diff --git a/WebCore/bindings/js/JSNodeCustom.cpp b/WebCore/bindings/js/JSNodeCustom.cpp index f375ae5..737430e 100644 --- a/WebCore/bindings/js/JSNodeCustom.cpp +++ b/WebCore/bindings/js/JSNodeCustom.cpp @@ -144,7 +144,7 @@ void JSNode::markChildren(MarkStack& markStack) // mark any other nodes. if (node->inDocument()) { if (Document* doc = node->ownerDocument()) - markDOMObjectWrapper(markStack, *Heap::heap(this)->globalData(), doc); + markDOMNodeWrapper(markStack, doc, doc); return; } @@ -154,7 +154,7 @@ void JSNode::markChildren(MarkStack& markStack) Node* outermostNodeWithWrapper = node; for (Node* current = m_impl.get(); current; current = current->parentNode()) { root = current; - if (hasCachedDOMNodeWrapper(current->document(), current)) + if (hasCachedDOMNodeWrapperUnchecked(current->document(), current)) outermostNodeWithWrapper = current; } diff --git a/WebCore/bindings/js/JSPopStateEventCustom.cpp b/WebCore/bindings/js/JSPopStateEventCustom.cpp index ee86a09..3f5fd7e 100644 --- a/WebCore/bindings/js/JSPopStateEventCustom.cpp +++ b/WebCore/bindings/js/JSPopStateEventCustom.cpp @@ -45,13 +45,4 @@ JSValue JSPopStateEvent::initPopStateEvent(ExecState* exec, const ArgList& args) return jsUndefined(); } -JSC::JSValue JSPopStateEvent::state(JSC::ExecState* exec) const -{ - SerializedScriptValue* object = static_cast<PopStateEvent*>(impl())->state(); - if (!object) - return JSC::jsNull(); - - return object->deserialize(exec); -} - } // namespace WebCore diff --git a/WebCore/bindings/js/JSQuarantinedObjectWrapper.cpp b/WebCore/bindings/js/JSQuarantinedObjectWrapper.cpp deleted file mode 100644 index ea2f72f..0000000 --- a/WebCore/bindings/js/JSQuarantinedObjectWrapper.cpp +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "JSQuarantinedObjectWrapper.h" - -#include "JSDOMBinding.h" - -#include <runtime/JSGlobalObject.h> - -using namespace JSC; - -namespace WebCore { - -ASSERT_CLASS_FITS_IN_CELL(JSQuarantinedObjectWrapper); - -const ClassInfo JSQuarantinedObjectWrapper::s_info = { "JSQuarantinedObjectWrapper", 0, 0, 0 }; - -JSQuarantinedObjectWrapper* JSQuarantinedObjectWrapper::asWrapper(JSValue value) -{ - if (!value.isObject()) - return 0; - - JSObject* object = asObject(value); - - if (!object->inherits(&JSQuarantinedObjectWrapper::s_info)) - return 0; - - return static_cast<JSQuarantinedObjectWrapper*>(object); -} - -JSValue JSQuarantinedObjectWrapper::cachedValueGetter(ExecState*, const Identifier&, const PropertySlot& slot) -{ - JSValue v = slot.slotBase(); - ASSERT(v); - return v; -} - -JSQuarantinedObjectWrapper::JSQuarantinedObjectWrapper(ExecState* unwrappedExec, JSObject* unwrappedObject, NonNullPassRefPtr<Structure> structure) - : JSObject(structure) - , m_unwrappedGlobalObject(unwrappedExec->lexicalGlobalObject()) - , m_unwrappedObject(unwrappedObject) -{ - ASSERT_ARG(unwrappedExec, unwrappedExec); - ASSERT_ARG(unwrappedObject, unwrappedObject); - ASSERT(this->structure()); -} - -JSQuarantinedObjectWrapper::~JSQuarantinedObjectWrapper() -{ -} - -bool JSQuarantinedObjectWrapper::allowsUnwrappedAccessFrom(ExecState* exec) const -{ - return m_unwrappedGlobalObject->profileGroup() == exec->lexicalGlobalObject()->profileGroup(); -} - -ExecState* JSQuarantinedObjectWrapper::unwrappedExecState() const -{ - return m_unwrappedGlobalObject->globalExec(); -} - -void JSQuarantinedObjectWrapper::transferExceptionToExecState(ExecState* exec) const -{ - ASSERT(exec != unwrappedExecState()); - - if (!unwrappedExecState()->hadException()) - return; - - JSValue exception = unwrappedExecState()->exception(); - unwrappedExecState()->clearException(); - exec->setException(wrapOutgoingValue(unwrappedExecState(), exception)); -} - -void JSQuarantinedObjectWrapper::markChildren(MarkStack& markStack) -{ - JSObject::markChildren(markStack); - - markStack.append(m_unwrappedObject); - markStack.append(m_unwrappedGlobalObject); -} - -bool JSQuarantinedObjectWrapper::getOwnPropertySlot(ExecState* exec, const Identifier& identifier, PropertySlot& slot) -{ - if (!allowsGetProperty()) { - slot.setUndefined(); - return true; - } - - PropertySlot unwrappedSlot(m_unwrappedObject); - bool result = m_unwrappedObject->getOwnPropertySlot(unwrappedExecState(), identifier, unwrappedSlot); - if (result) { - JSValue unwrappedValue = unwrappedSlot.getValue(unwrappedExecState(), identifier); - slot.setCustom(wrapOutgoingValue(unwrappedExecState(), unwrappedValue), cachedValueGetter); - } - - transferExceptionToExecState(exec); - - return result; -} - -bool JSQuarantinedObjectWrapper::getOwnPropertySlot(ExecState* exec, unsigned identifier, PropertySlot& slot) -{ - if (!allowsGetProperty()) { - slot.setUndefined(); - return true; - } - - PropertySlot unwrappedSlot(m_unwrappedObject); - bool result = m_unwrappedObject->getOwnPropertySlot(unwrappedExecState(), identifier, unwrappedSlot); - if (result) { - JSValue unwrappedValue = unwrappedSlot.getValue(unwrappedExecState(), identifier); - slot.setCustom(wrapOutgoingValue(unwrappedExecState(), unwrappedValue), cachedValueGetter); - } - - transferExceptionToExecState(exec); - - return result; -} - -bool JSQuarantinedObjectWrapper::getOwnPropertyDescriptor(ExecState* exec, const Identifier& identifier, PropertyDescriptor& descriptor) -{ - if (!allowsGetProperty()) { - descriptor.setUndefined(); - return true; - } - - PropertyDescriptor unwrappedDescriptor; - bool result = m_unwrappedObject->getOwnPropertyDescriptor(unwrappedExecState(), identifier, unwrappedDescriptor); - - if (unwrappedDescriptor.isAccessorDescriptor()) { - descriptor.setAccessorDescriptor(wrapOutgoingValue(unwrappedExecState(), unwrappedDescriptor.getter()), - wrapOutgoingValue(unwrappedExecState(), unwrappedDescriptor.setter()), - unwrappedDescriptor.attributes()); - } else - descriptor.setDescriptor(wrapOutgoingValue(unwrappedExecState(), unwrappedDescriptor.value()), unwrappedDescriptor.attributes()); - transferExceptionToExecState(exec); - return result; -} - -void JSQuarantinedObjectWrapper::put(ExecState* exec, const Identifier& identifier, JSValue value, PutPropertySlot& slot) -{ - if (!allowsSetProperty()) - return; - - m_unwrappedObject->put(unwrappedExecState(), identifier, prepareIncomingValue(exec, value), slot); - - transferExceptionToExecState(exec); -} - -void JSQuarantinedObjectWrapper::put(ExecState* exec, unsigned identifier, JSValue value) -{ - if (!allowsSetProperty()) - return; - - m_unwrappedObject->put(unwrappedExecState(), identifier, prepareIncomingValue(exec, value)); - - transferExceptionToExecState(exec); -} - -bool JSQuarantinedObjectWrapper::defineOwnProperty(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool shouldThrow) -{ - if (!allowsSetProperty()) - return false; - - PropertyDescriptor wrappedDescriptor; - if (descriptor.isDataDescriptor()) { - wrappedDescriptor.setValue(prepareIncomingValue(exec, descriptor.value())); - if (wrappedDescriptor.writablePresent()) - wrappedDescriptor.setWritable(descriptor.writable()); - } else if (descriptor.isAccessorDescriptor()) { - if (descriptor.getter()) - wrappedDescriptor.setGetter(prepareIncomingValue(exec, descriptor.getter())); - if (descriptor.setter()) - wrappedDescriptor.setSetter(prepareIncomingValue(exec, descriptor.setter())); - } - if (wrappedDescriptor.enumerablePresent()) - wrappedDescriptor.setEnumerable(descriptor.enumerable()); - if (wrappedDescriptor.configurablePresent()) - wrappedDescriptor.setConfigurable(descriptor.configurable()); - - bool result = m_unwrappedObject->defineOwnProperty(unwrappedExecState(), propertyName, wrappedDescriptor, shouldThrow); - - transferExceptionToExecState(exec); - return result; -} - -bool JSQuarantinedObjectWrapper::deleteProperty(ExecState* exec, const Identifier& identifier) -{ - if (!allowsDeleteProperty()) - return false; - - bool result = m_unwrappedObject->deleteProperty(unwrappedExecState(), identifier); - - transferExceptionToExecState(exec); - - return result; -} - -bool JSQuarantinedObjectWrapper::deleteProperty(ExecState* exec, unsigned identifier) -{ - if (!allowsDeleteProperty()) - return false; - - bool result = m_unwrappedObject->deleteProperty(unwrappedExecState(), identifier); - - transferExceptionToExecState(exec); - - return result; -} - -JSObject* JSQuarantinedObjectWrapper::construct(ExecState* exec, JSObject* constructor, const ArgList& args) -{ - JSQuarantinedObjectWrapper* wrapper = static_cast<JSQuarantinedObjectWrapper*>(constructor); - - MarkedArgumentBuffer preparedArgs; - for (size_t i = 0; i < args.size(); ++i) - preparedArgs.append(wrapper->prepareIncomingValue(exec, args.at(i))); - - // FIXME: Would be nice to find a way to reuse the result of m_unwrappedObject->getConstructData - // from when we called it in JSQuarantinedObjectWrapper::getConstructData. - ConstructData unwrappedConstructData; - ConstructType unwrappedConstructType = wrapper->m_unwrappedObject->getConstructData(unwrappedConstructData); - ASSERT(unwrappedConstructType != ConstructTypeNone); - - JSValue unwrappedResult = JSC::construct(wrapper->unwrappedExecState(), wrapper->m_unwrappedObject, unwrappedConstructType, unwrappedConstructData, preparedArgs); - JSValue resultValue = wrapper->wrapOutgoingValue(wrapper->unwrappedExecState(), unwrappedResult); - ASSERT(resultValue.isObject()); - JSObject* result = asObject(resultValue); - - wrapper->transferExceptionToExecState(exec); - - return result; -} - -ConstructType JSQuarantinedObjectWrapper::getConstructData(ConstructData& constructData) -{ - if (!allowsConstruct()) - return ConstructTypeNone; - ConstructData unwrappedConstructData; - if (m_unwrappedObject->getConstructData(unwrappedConstructData) == ConstructTypeNone) - return ConstructTypeNone; - constructData.native.function = construct; - return ConstructTypeHost; -} - -bool JSQuarantinedObjectWrapper::hasInstance(ExecState* exec, JSValue value, JSValue proto) -{ - if (!allowsHasInstance()) - return false; - - bool result = m_unwrappedObject->hasInstance(unwrappedExecState(), prepareIncomingValue(exec, value), prepareIncomingValue(exec, proto)); - - transferExceptionToExecState(exec); - - return result; -} - -JSValue JSQuarantinedObjectWrapper::call(ExecState* exec, JSObject* function, JSValue thisValue, const ArgList& args) -{ - JSQuarantinedObjectWrapper* wrapper = static_cast<JSQuarantinedObjectWrapper*>(function); - - JSValue preparedThisValue = wrapper->prepareIncomingValue(exec, thisValue); - - MarkedArgumentBuffer preparedArgs; - for (size_t i = 0; i < args.size(); ++i) - preparedArgs.append(wrapper->prepareIncomingValue(exec, args.at(i))); - - // FIXME: Would be nice to find a way to reuse the result of m_unwrappedObject->getCallData - // from when we called it in JSQuarantinedObjectWrapper::getCallData. - CallData unwrappedCallData; - CallType unwrappedCallType = wrapper->m_unwrappedObject->getCallData(unwrappedCallData); - ASSERT(unwrappedCallType != CallTypeNone); - - JSValue unwrappedResult = JSC::call(wrapper->unwrappedExecState(), wrapper->m_unwrappedObject, unwrappedCallType, unwrappedCallData, preparedThisValue, preparedArgs); - JSValue result = wrapper->wrapOutgoingValue(wrapper->unwrappedExecState(), unwrappedResult); - - wrapper->transferExceptionToExecState(exec); - - return result; -} - -CallType JSQuarantinedObjectWrapper::getCallData(CallData& callData) -{ - if (!allowsCallAsFunction()) - return CallTypeNone; - CallData unwrappedCallData; - if (m_unwrappedObject->getCallData(unwrappedCallData) == CallTypeNone) - return CallTypeNone; - callData.native.function = call; - return CallTypeHost; -} - -void JSQuarantinedObjectWrapper::getPropertyNames(ExecState*, PropertyNameArray& array) -{ - if (!allowsGetPropertyNames()) - return; - - m_unwrappedObject->getPropertyNames(unwrappedExecState(), array); -} - -void JSQuarantinedObjectWrapper::getOwnPropertyNames(ExecState*, PropertyNameArray& array) -{ - if (!allowsGetPropertyNames()) - return; - - m_unwrappedObject->getOwnPropertyNames(unwrappedExecState(), array); -} - -} // namespace WebCore diff --git a/WebCore/bindings/js/JSQuarantinedObjectWrapper.h b/WebCore/bindings/js/JSQuarantinedObjectWrapper.h deleted file mode 100644 index 9f62495..0000000 --- a/WebCore/bindings/js/JSQuarantinedObjectWrapper.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef JSQuarantinedObjectWrapper_h -#define JSQuarantinedObjectWrapper_h - -#include <runtime/JSObject.h> - -namespace WebCore { - - class JSQuarantinedObjectWrapper : public JSC::JSObject { - public: - static JSQuarantinedObjectWrapper* asWrapper(JSC::JSValue); - - virtual ~JSQuarantinedObjectWrapper(); - - virtual JSC::JSObject* unwrappedObject() { return m_unwrappedObject; } - - JSC::JSGlobalObject* unwrappedGlobalObject() const { return m_unwrappedGlobalObject; }; - JSC::ExecState* unwrappedExecState() const; - - bool allowsUnwrappedAccessFrom(JSC::ExecState*) const; - - static const JSC::ClassInfo s_info; - - static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue proto) - { - return JSC::Structure::create(proto, JSC::TypeInfo(JSC::ObjectType, StructureFlags)); - } - - protected: - static const unsigned StructureFlags = JSC::OverridesGetOwnPropertySlot | JSC::ImplementsHasInstance | JSC::OverridesHasInstance | JSC::OverridesMarkChildren | JSC::OverridesGetPropertyNames | JSC::JSObject::StructureFlags; - - JSQuarantinedObjectWrapper(JSC::ExecState* unwrappedExec, JSC::JSObject* unwrappedObject, NonNullPassRefPtr<JSC::Structure>); - - virtual void markChildren(JSC::MarkStack&); - - private: - virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&); - virtual bool getOwnPropertySlot(JSC::ExecState*, unsigned, JSC::PropertySlot&); - virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&); - - virtual void put(JSC::ExecState*, const JSC::Identifier&, JSC::JSValue, JSC::PutPropertySlot&); - virtual void put(JSC::ExecState*, unsigned, JSC::JSValue); - virtual bool defineOwnProperty(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&, bool shouldThrow); - - virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier&); - virtual bool deleteProperty(JSC::ExecState*, unsigned); - - virtual JSC::CallType getCallData(JSC::CallData&); - virtual JSC::ConstructType getConstructData(JSC::ConstructData&); - - virtual bool hasInstance(JSC::ExecState*, JSC::JSValue, JSC::JSValue proto); - - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); - virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); - - virtual JSC::UString className() const { return m_unwrappedObject->className(); } - - virtual bool allowsGetProperty() const { return false; } - virtual bool allowsSetProperty() const { return false; } - virtual bool allowsDeleteProperty() const { return false; } - virtual bool allowsConstruct() const { return false; } - virtual bool allowsHasInstance() const { return false; } - virtual bool allowsCallAsFunction() const { return false; } - virtual bool allowsGetPropertyNames() const { return false; } - - virtual JSC::JSValue prepareIncomingValue(JSC::ExecState* unwrappedExec, JSC::JSValue unwrappedValue) const = 0; - virtual JSC::JSValue wrapOutgoingValue(JSC::ExecState* unwrappedExec, JSC::JSValue unwrappedValue) const = 0; - - static JSC::JSValue cachedValueGetter(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&); - - void transferExceptionToExecState(JSC::ExecState*) const; - - static JSC::JSValue JSC_HOST_CALL call(JSC::ExecState*, JSC::JSObject* function, JSC::JSValue thisValue, const JSC::ArgList&); - static JSC::JSObject* construct(JSC::ExecState*, JSC::JSObject*, const JSC::ArgList&); - - JSC::JSGlobalObject* m_unwrappedGlobalObject; - JSC::JSObject* m_unwrappedObject; - }; - -} // namespace WebCore - -#endif // JSQuarantinedObjectWrapper_h diff --git a/WebCore/bindings/js/JSSVGContextCache.h b/WebCore/bindings/js/JSSVGContextCache.h new file mode 100644 index 0000000..75ed324 --- /dev/null +++ b/WebCore/bindings/js/JSSVGContextCache.h @@ -0,0 +1,97 @@ +/* + Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. + + 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 JSSVGContextCache_h +#define JSSVGContextCache_h + +#if ENABLE(SVG) +#include "SVGElement.h" +#include <wtf/StdLibExtras.h> + +namespace WebCore { + +class DOMObject; + +class JSSVGContextCache : public Noncopyable { +public: + typedef HashMap<DOMObject*, SVGElement*> WrapperMap; + + static WrapperMap& wrapperMap() + { + DEFINE_STATIC_LOCAL(WrapperMap, s_wrapperMap, ()); + return s_wrapperMap; + } + + static void addWrapper(DOMObject* wrapper, SVGElement* context) + { + ASSERT(wrapper); + ASSERT(context); + + pair<WrapperMap::iterator, bool> result = wrapperMap().add(wrapper, context); + if (result.second) { + WrapperMap::iterator& it = result.first; + ASSERT_UNUSED(it, it->second == context); + } + } + + static void forgetWrapper(DOMObject* wrapper) + { + ASSERT(wrapper); + + WrapperMap& map = wrapperMap(); + WrapperMap::iterator it = map.find(wrapper); + if (it == map.end()) + return; + + map.remove(it); + } + + static void propagateSVGDOMChange(DOMObject* wrapper, const QualifiedName& attributeName) + { + WrapperMap& map = wrapperMap(); + WrapperMap::iterator it = map.find(wrapper); + if (it == map.end()) + return; + + SVGElement* context = it->second; + ASSERT(context); + + context->svgAttributeChanged(attributeName); + } + + static SVGElement* svgContextForDOMObject(DOMObject* wrapper) + { + ASSERT(wrapper); + + WrapperMap& map = wrapperMap(); + WrapperMap::iterator it = map.find(wrapper); + if (it == map.end()) + return 0; + + SVGElement* context = it->second; + ASSERT(context); + return context; + } + +}; + +} + +#endif +#endif diff --git a/WebCore/bindings/js/JSSVGLengthCustom.cpp b/WebCore/bindings/js/JSSVGLengthCustom.cpp index bad52ae..33bbf30 100644 --- a/WebCore/bindings/js/JSSVGLengthCustom.cpp +++ b/WebCore/bindings/js/JSSVGLengthCustom.cpp @@ -28,18 +28,22 @@ namespace WebCore { JSValue JSSVGLength::value(ExecState* exec) const { - SVGLength imp(*impl()); - return jsNumber(exec, imp.value(context())); + JSSVGPODTypeWrapper<SVGLength>* imp = impl(); + SVGElement* context = JSSVGContextCache::svgContextForDOMObject(const_cast<JSSVGLength*>(this)); + + SVGLength podImp(*imp); + return jsNumber(exec, podImp.value(context)); } JSValue JSSVGLength::convertToSpecifiedUnits(ExecState* exec, const ArgList& args) { - JSSVGPODTypeWrapper<SVGLength>* wrapper = impl(); + JSSVGPODTypeWrapper<SVGLength>* imp = impl(); + SVGElement* context = JSSVGContextCache::svgContextForDOMObject(this); - SVGLength imp(*wrapper); - imp.convertToSpecifiedUnits(args.at(0).toInt32(exec), context()); + SVGLength podImp(*imp); + podImp.convertToSpecifiedUnits(args.at(0).toInt32(exec), context); - wrapper->commitChange(imp, context()); + imp->commitChange(podImp, this); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSSVGMatrixCustom.cpp b/WebCore/bindings/js/JSSVGMatrixCustom.cpp index a9d0e54..d2d3d6f 100644 --- a/WebCore/bindings/js/JSSVGMatrixCustom.cpp +++ b/WebCore/bindings/js/JSSVGMatrixCustom.cpp @@ -44,15 +44,16 @@ JSValue JSSVGMatrix::multiply(ExecState* exec, const ArgList& args) TransformationMatrix m1(*impl()); TransformationMatrix m2(*(matrixObj->impl())); - JSC::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), JSSVGStaticPODTypeWrapper<TransformationMatrix>::create(m1.multLeft(m2)).get(), m_context.get()); - - return result; + SVGElement* context = JSSVGContextCache::svgContextForDOMObject(this); + return toJS(exec, globalObject(), JSSVGStaticPODTypeWrapper<TransformationMatrix>::create(m1.multLeft(m2)).get(), context); } JSValue JSSVGMatrix::inverse(ExecState* exec, const ArgList&) { TransformationMatrix imp(*impl()); - JSC::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), JSSVGStaticPODTypeWrapper<TransformationMatrix>::create(imp.inverse()).get(), m_context.get()); + + SVGElement* context = JSSVGContextCache::svgContextForDOMObject(this); + JSValue result = toJS(exec, globalObject(), JSSVGStaticPODTypeWrapper<TransformationMatrix>::create(imp.inverse()).get(), context); if (!imp.isInvertible()) setDOMException(exec, SVGException::SVG_MATRIX_NOT_INVERTABLE); @@ -67,7 +68,8 @@ JSValue JSSVGMatrix::rotateFromVector(ExecState* exec, const ArgList& args) float x = args.at(0).toFloat(exec); float y = args.at(1).toFloat(exec); - JSC::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), JSSVGStaticPODTypeWrapper<TransformationMatrix>::create(imp.rotateFromVector(x, y)).get(), m_context.get()); + SVGElement* context = JSSVGContextCache::svgContextForDOMObject(this); + JSValue result = toJS(exec, globalObject(), JSSVGStaticPODTypeWrapper<TransformationMatrix>::create(imp.rotateFromVector(x, y)).get(), context); if (x == 0.0 || y == 0.0) setDOMException(exec, SVGException::SVG_INVALID_VALUE_ERR); diff --git a/WebCore/bindings/js/JSSVGPODListCustom.h b/WebCore/bindings/js/JSSVGPODListCustom.h new file mode 100644 index 0000000..8a0654c --- /dev/null +++ b/WebCore/bindings/js/JSSVGPODListCustom.h @@ -0,0 +1,199 @@ +/* + * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * Copyright (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * 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 JSSVGPODListCustom_h +#define JSSVGPODListCustom_h + +#include "JSSVGContextCache.h" +#include "JSSVGPODTypeWrapper.h" +#include "SVGList.h" + +namespace WebCore { + +namespace JSSVGPODListCustom { + +// Helper structure only containing public typedefs, as C++ does not allow templatized typedefs +template<typename PODType> +struct JSSVGPODListTraits { + typedef SVGPODListItem<PODType> PODListItem; + typedef SVGList<RefPtr<PODListItem> > PODList; + typedef PODType (*ConversionCallback)(JSC::JSValue); +}; + +template<typename JSPODListType, typename PODType> +static JSC::JSValue finishGetter(JSC::ExecState* exec, ExceptionCode& ec, JSPODListType* wrapper, + PassRefPtr<typename JSSVGPODListTraits<PODType>::PODListItem> item) +{ + if (ec) { + setDOMException(exec, ec); + return JSC::jsUndefined(); + } + + typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl(); + + SVGElement* context = JSSVGContextCache::svgContextForDOMObject(wrapper); + return toJS(exec, wrapper->globalObject(), + JSSVGPODTypeWrapperCreatorForList<PODType>::create(item.get(), listImp->associatedAttributeName()).get(), context); +} + +template<typename JSPODListType, typename PODType> +static JSC::JSValue finishSetter(JSC::ExecState* exec, ExceptionCode& ec, JSPODListType* wrapper, + PassRefPtr<typename JSSVGPODListTraits<PODType>::PODListItem> item) +{ + if (ec) { + setDOMException(exec, ec); + return JSC::jsUndefined(); + } + + typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl(); + + const QualifiedName& attributeName = listImp->associatedAttributeName(); + JSSVGContextCache::propagateSVGDOMChange(wrapper, attributeName); + + SVGElement* context = JSSVGContextCache::svgContextForDOMObject(wrapper); + return toJS(exec, wrapper->globalObject(), + JSSVGPODTypeWrapperCreatorForList<PODType>::create(item.get(), attributeName).get(), context); +} + +template<typename JSPODListType, typename PODType> +static JSC::JSValue finishSetterReadOnlyResult(JSC::ExecState* exec, ExceptionCode& ec, JSPODListType* wrapper, + PassRefPtr<typename JSSVGPODListTraits<PODType>::PODListItem> item) +{ + if (ec) { + setDOMException(exec, ec); + return JSC::jsUndefined(); + } + + typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl(); + JSSVGContextCache::propagateSVGDOMChange(wrapper, listImp->associatedAttributeName()); + return toJS(exec, wrapper->globalObject(), + JSSVGStaticPODTypeWrapper<PODType>::create(*item).get(), 0 /* no context on purpose */); +} + +template<typename JSPODListType, typename PODType> +static JSC::JSValue clear(JSPODListType* wrapper, JSC::ExecState* exec, const JSC::ArgList&, + typename JSSVGPODListTraits<PODType>::ConversionCallback) +{ + ExceptionCode ec = 0; + typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl(); + listImp->clear(ec); + + if (ec) + setDOMException(exec, ec); + else + JSSVGContextCache::propagateSVGDOMChange(wrapper, listImp->associatedAttributeName()); + + return JSC::jsUndefined(); +} + +template<typename JSPODListType, typename PODType> +static JSC::JSValue initialize(JSPODListType* wrapper, JSC::ExecState* exec, const JSC::ArgList& args, + typename JSSVGPODListTraits<PODType>::ConversionCallback conversion) +{ + ExceptionCode ec = 0; + typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl(); + return finishSetter<JSPODListType, PODType>(exec, ec, wrapper, + listImp->initialize(JSSVGPODListTraits<PODType>::PODListItem::copy(conversion(args.at(0))), ec)); +} + +template<typename JSPODListType, typename PODType> +static JSC::JSValue getItem(JSPODListType* wrapper, JSC::ExecState* exec, const JSC::ArgList& args, + typename JSSVGPODListTraits<PODType>::ConversionCallback) +{ + bool indexOk = false; + unsigned index = args.at(0).toUInt32(exec, indexOk); + if (!indexOk) { + setDOMException(exec, TYPE_MISMATCH_ERR); + return JSC::jsUndefined(); + } + + ExceptionCode ec = 0; + typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl(); + return finishGetter<JSPODListType, PODType>(exec, ec, wrapper, + listImp->getItem(index, ec)); +} + +template<typename JSPODListType, typename PODType> +static JSC::JSValue insertItemBefore(JSPODListType* wrapper, JSC::ExecState* exec, const JSC::ArgList& args, + typename JSSVGPODListTraits<PODType>::ConversionCallback conversion) +{ + bool indexOk = false; + unsigned index = args.at(1).toUInt32(exec, indexOk); + if (!indexOk) { + setDOMException(exec, TYPE_MISMATCH_ERR); + return JSC::jsUndefined(); + } + + ExceptionCode ec = 0; + typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl(); + return finishSetter<JSPODListType, PODType>(exec, ec, wrapper, + listImp->insertItemBefore(JSSVGPODListTraits<PODType>::PODListItem::copy(conversion(args.at(0))), index, ec)); +} + +template<typename JSPODListType, typename PODType> +static JSC::JSValue replaceItem(JSPODListType* wrapper, JSC::ExecState* exec, const JSC::ArgList& args, + typename JSSVGPODListTraits<PODType>::ConversionCallback conversion) +{ + bool indexOk = false; + unsigned index = args.at(1).toUInt32(exec, indexOk); + if (!indexOk) { + setDOMException(exec, TYPE_MISMATCH_ERR); + return JSC::jsUndefined(); + } + + ExceptionCode ec = 0; + typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl(); + return finishSetter<JSPODListType, PODType>(exec, ec, wrapper, + listImp->replaceItem(JSSVGPODListTraits<PODType>::PODListItem::copy(conversion(args.at(0))), index, ec)); +} + +template<typename JSPODListType, typename PODType> +static JSC::JSValue removeItem(JSPODListType* wrapper, JSC::ExecState* exec, const JSC::ArgList& args, + typename JSSVGPODListTraits<PODType>::ConversionCallback) +{ + bool indexOk = false; + unsigned index = args.at(0).toUInt32(exec, indexOk); + if (!indexOk) { + setDOMException(exec, TYPE_MISMATCH_ERR); + return JSC::jsUndefined(); + } + + ExceptionCode ec = 0; + typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl(); + return finishSetterReadOnlyResult<JSPODListType, PODType>(exec, ec, wrapper, + listImp->removeItem(index, ec)); +} + +template<typename JSPODListType, typename PODType> +static JSC::JSValue appendItem(JSPODListType* wrapper, JSC::ExecState* exec, const JSC::ArgList& args, + typename JSSVGPODListTraits<PODType>::ConversionCallback conversion) +{ + ExceptionCode ec = 0; + typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl(); + return finishSetter<JSPODListType, PODType>(exec, ec, wrapper, + listImp->appendItem(JSSVGPODListTraits<PODType>::PODListItem::copy(conversion(args.at(0))), ec)); +} + +} + +} + +#endif diff --git a/WebCore/bindings/js/JSSVGPODTypeWrapper.h b/WebCore/bindings/js/JSSVGPODTypeWrapper.h index 51e4e9e..7c04f22 100644 --- a/WebCore/bindings/js/JSSVGPODTypeWrapper.h +++ b/WebCore/bindings/js/JSSVGPODTypeWrapper.h @@ -28,25 +28,28 @@ #define JSSVGPODTypeWrapper_h #if ENABLE(SVG) +#include "JSSVGContextCache.h" #include "SVGElement.h" #include <wtf/StdLibExtras.h> namespace WebCore { +class DOMObject; + template<typename PODType> class JSSVGPODTypeWrapper : public RefCounted<JSSVGPODTypeWrapper<PODType> > { public: virtual ~JSSVGPODTypeWrapper() { } virtual operator PODType() = 0; - virtual void commitChange(PODType, SVGElement*) = 0; + virtual void commitChange(PODType, DOMObject*) = 0; }; // This file contains JS wrapper objects for SVG datatypes, that are passed around by value // in WebCore/svg (aka. 'POD types'). For instance SVGMatrix is mapped to TransformationMatrix, and // passed around as const reference. SVG DOM demands these objects to be "live", changes to any // of the writable attributes of SVGMatrix need to be reflected in the object which exposed the -// SVGMatrix object (ie. 'someElement.transform.matrix.a = 50.0', in that case 'SVGTransform'). +// SVGMatrix object (i.e. 'someElement.transform.matrix.a = 50.0', in that case 'SVGTransform'). // The SVGTransform class stores its "TransformationMatrix m_matrix" object on the stack. If it would // be stored as pointer we could just build an auto-generated JSSVG* wrapper object around it // and all changes to that object would automatically affect the TransformationMatrix* object stored @@ -68,13 +71,13 @@ public: // GetterMethod and SetterMethod are each 12 bytes. We have to pack to a size // greater than or equal to that to avoid an alignment warning (C4121). 16 is // the next-largest size allowed for packing, so we use that. -#pragma pack(16) +#pragma pack(push, 16) #endif template<typename PODType, typename PODTypeCreator> class JSSVGDynamicPODTypeWrapper : public JSSVGPODTypeWrapper<PODType> { public: typedef PODType (PODTypeCreator::*GetterMethod)() const; - typedef void (PODTypeCreator::*SetterMethod)(PODType); + typedef void (PODTypeCreator::*SetterMethod)(const PODType&); static PassRefPtr<JSSVGDynamicPODTypeWrapper> create(PassRefPtr<PODTypeCreator> creator, GetterMethod getter, SetterMethod setter) { @@ -86,12 +89,10 @@ public: return (m_creator.get()->*m_getter)(); } - virtual void commitChange(PODType type, SVGElement* context) + virtual void commitChange(PODType type, DOMObject* wrapper) { (m_creator.get()->*m_setter)(type); - - if (context) - context->svgAttributeChanged(m_creator->associatedAttributeName()); + JSSVGContextCache::propagateSVGDOMChange(wrapper, m_creator->associatedAttributeName()); } private: @@ -105,15 +106,20 @@ private: ASSERT(m_setter); } + virtual ~JSSVGDynamicPODTypeWrapper(); + // Update callbacks RefPtr<PODTypeCreator> m_creator; GetterMethod m_getter; SetterMethod m_setter; }; +#if COMPILER(MSVC) +#pragma pack(pop) +#endif -// Represents a JS wrapper object for SVG POD types (not for SVGAnimated* clases). Any modification to the SVG POD +// Represents a JS wrapper object for SVG POD types (not for SVGAnimated* classes). Any modification to the SVG POD // types don't cause any updates unlike JSSVGDynamicPODTypeWrapper. This class is used for return values (ie. getBBox()) -// and for properties where SVG specification explicitely states, that the contents of the POD type are immutable. +// and for properties where SVG specification explicitly states, that the contents of the POD type are immutable. template<typename PODType> class JSSVGStaticPODTypeWrapper : public JSSVGPODTypeWrapper<PODType> { @@ -128,7 +134,7 @@ public: return m_podType; } - virtual void commitChange(PODType type, SVGElement*) + virtual void commitChange(PODType type, DOMObject*) { m_podType = type; } @@ -152,10 +158,10 @@ public: return adoptRef(new JSSVGStaticPODTypeWrapperWithPODTypeParent(type, parent)); } - virtual void commitChange(PODType type, SVGElement* context) + virtual void commitChange(PODType type, DOMObject* wrapper) { - JSSVGStaticPODTypeWrapper<PODType>::commitChange(type, context); - m_parentType->commitChange(ParentTypeArg(type), context); + JSSVGStaticPODTypeWrapper<PODType>::commitChange(type, wrapper); + m_parentType->commitChange(ParentTypeArg(type), wrapper); } private: @@ -172,7 +178,7 @@ private: // GetterMethod and SetterMethod are each 12 bytes. We have to pack to a size // greater than or equal to that to avoid an alignment warning (C4121). 16 is // the next-largest size allowed for packing, so we use that. -#pragma pack(16) +#pragma pack(push, 16) #endif template<typename PODType, typename ParentType> class JSSVGStaticPODTypeWrapperWithParent : public JSSVGPODTypeWrapper<PODType> { @@ -190,7 +196,7 @@ public: return (m_parent.get()->*m_getter)(); } - virtual void commitChange(PODType type, SVGElement*) + virtual void commitChange(PODType type, DOMObject*) { (m_parent.get()->*m_setter)(type); } @@ -223,7 +229,7 @@ public: typedef SVGPODListItem<PODType> PODListItemPtrType; typedef PODType (SVGPODListItem<PODType>::*GetterMethod)() const; - typedef void (SVGPODListItem<PODType>::*SetterMethod)(PODType); + typedef void (SVGPODListItem<PODType>::*SetterMethod)(const PODType&); static PassRefPtr<JSSVGPODTypeWrapperCreatorForList> create(PassRefPtr<PODListItemPtrType> creator, const QualifiedName& attributeName) { @@ -235,15 +241,13 @@ public: return (m_creator.get()->*m_getter)(); } - virtual void commitChange(PODType type, SVGElement* context) + virtual void commitChange(PODType type, DOMObject* wrapper) { if (!m_setter) return; (m_creator.get()->*m_setter)(type); - - if (context) - context->svgAttributeChanged(m_associatedAttributeName); + JSSVGContextCache::propagateSVGDOMChange(wrapper, m_associatedAttributeName); } private: @@ -269,7 +273,7 @@ private: template<typename PODType, typename PODTypeCreator> struct PODTypeWrapperCacheInfo { typedef PODType (PODTypeCreator::*GetterMethod)() const; - typedef void (PODTypeCreator::*SetterMethod)(PODType); + typedef void (PODTypeCreator::*SetterMethod)(const PODType&); // Empty value PODTypeWrapperCacheInfo() @@ -309,6 +313,9 @@ struct PODTypeWrapperCacheInfo { GetterMethod getter; SetterMethod setter; }; +#if COMPILER(MSVC) +#pragma pack(pop) +#endif template<typename PODType, typename PODTypeCreator> struct PODTypeWrapperCacheInfoHash { @@ -351,60 +358,53 @@ struct PODTypeWrapperCacheInfoTraits : WTF::GenericHashTraits<PODTypeWrapperCach } }; +// Used for dynamic read-write attributes template<typename PODType, typename PODTypeCreator> class JSSVGDynamicPODTypeWrapperCache { public: typedef PODType (PODTypeCreator::*GetterMethod)() const; - typedef void (PODTypeCreator::*SetterMethod)(PODType); + typedef void (PODTypeCreator::*SetterMethod)(const PODType&); typedef PODTypeWrapperCacheInfo<PODType, PODTypeCreator> CacheInfo; typedef PODTypeWrapperCacheInfoHash<PODType, PODTypeCreator> CacheInfoHash; typedef PODTypeWrapperCacheInfoTraits<PODType, PODTypeCreator> CacheInfoTraits; typedef JSSVGPODTypeWrapper<PODType> WrapperBase; - typedef JSSVGDynamicPODTypeWrapper<PODType, PODTypeCreator> DynamicWrapper; - typedef HashMap<CacheInfo, DynamicWrapper*, CacheInfoHash, CacheInfoTraits> DynamicWrapperHashMap; - typedef typename DynamicWrapperHashMap::const_iterator DynamicWrapperHashMapIterator; + typedef JSSVGDynamicPODTypeWrapper<PODType, PODTypeCreator> Wrapper; + typedef HashMap<CacheInfo, Wrapper*, CacheInfoHash, CacheInfoTraits> WrapperMap; - static DynamicWrapperHashMap& dynamicWrapperHashMap() + static WrapperMap& wrapperMap() { - DEFINE_STATIC_LOCAL(DynamicWrapperHashMap, s_dynamicWrapperHashMap, ()); - return s_dynamicWrapperHashMap; + DEFINE_STATIC_LOCAL(WrapperMap, s_wrapperMap, ()); + return s_wrapperMap; } - // Used for readwrite attributes only static PassRefPtr<WrapperBase> lookupOrCreateWrapper(PODTypeCreator* creator, GetterMethod getter, SetterMethod setter) { - DynamicWrapperHashMap& map(dynamicWrapperHashMap()); CacheInfo info(creator, getter, setter); + pair<typename WrapperMap::iterator, bool> result = wrapperMap().add(info, 0); + if (!result.second) // pre-existing entry + return result.first->second; - if (map.contains(info)) - return map.get(info); - - RefPtr<DynamicWrapper> wrapper = DynamicWrapper::create(creator, getter, setter); - map.set(info, wrapper.get()); + RefPtr<Wrapper> wrapper = Wrapper::create(creator, getter, setter); + result.first->second = wrapper.get(); return wrapper.release(); } - static void forgetWrapper(WrapperBase* wrapper) + static void forgetWrapper(PODTypeCreator* creator, GetterMethod getter, SetterMethod setter) { - DynamicWrapperHashMap& map(dynamicWrapperHashMap()); - - DynamicWrapperHashMapIterator it = map.begin(); - DynamicWrapperHashMapIterator end = map.end(); - - for (; it != end; ++it) { - if (it->second != wrapper) - continue; - - // It's guaranteed that there's just one object we need to take care of. - map.remove(it->first); - break; - } + CacheInfo info(creator, getter, setter); + wrapperMap().remove(info); } }; -}; +template<typename PODType, typename PODTypeCreator> +JSSVGDynamicPODTypeWrapper<PODType, PODTypeCreator>::~JSSVGDynamicPODTypeWrapper() +{ + JSSVGDynamicPODTypeWrapperCache<PODType, PODTypeCreator>::forgetWrapper(m_creator.get(), m_getter, m_setter); +} + +} // namespace WebCore #endif // ENABLE(SVG) #endif // JSSVGPODTypeWrapper_h diff --git a/WebCore/bindings/js/JSSVGPathSegCustom.cpp b/WebCore/bindings/js/JSSVGPathSegCustom.cpp index d5be3fd..eac2c4b 100644 --- a/WebCore/bindings/js/JSSVGPathSegCustom.cpp +++ b/WebCore/bindings/js/JSSVGPathSegCustom.cpp @@ -21,6 +21,8 @@ #if ENABLE(SVG) #include "JSSVGPathSeg.h" + +#include "JSDOMBinding.h" #include "JSSVGPathSegArcAbs.h" #include "JSSVGPathSegArcRel.h" #include "JSSVGPathSegClosePath.h" @@ -40,9 +42,6 @@ #include "JSSVGPathSegLinetoVerticalRel.h" #include "JSSVGPathSegMovetoAbs.h" #include "JSSVGPathSegMovetoRel.h" - -#include "JSDOMBinding.h" - #include "SVGPathSeg.h" #include "SVGPathSegArc.h" #include "SVGPathSegClosePath.h" @@ -64,8 +63,10 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, SVGPathSeg* objec if (!object) return jsNull(); - if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec, object)) + if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec, object)) { + ASSERT(JSSVGContextCache::svgContextForDOMObject(wrapper) == context); return wrapper; + } switch (object->pathSegType()) { case SVGPathSeg::PATHSEG_CLOSEPATH: @@ -115,5 +116,3 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, SVGPathSeg* objec } #endif // ENABLE(SVG) - -// vim:ts=4:noet diff --git a/WebCore/bindings/js/JSSVGPathSegListCustom.cpp b/WebCore/bindings/js/JSSVGPathSegListCustom.cpp index b71f3a6..4831727 100644 --- a/WebCore/bindings/js/JSSVGPathSegListCustom.cpp +++ b/WebCore/bindings/js/JSSVGPathSegListCustom.cpp @@ -24,6 +24,7 @@ #include "Document.h" #include "Frame.h" +#include "JSSVGContextCache.h" #include "JSSVGPathSeg.h" #include "SVGDocumentExtensions.h" #include "SVGElement.h" @@ -39,12 +40,12 @@ JSValue JSSVGPathSegList::clear(ExecState* exec, const ArgList&) { ExceptionCode ec = 0; - SVGPathSegList* imp = static_cast<SVGPathSegList*>(impl()); - imp->clear(ec); + SVGPathSegList* list = impl(); + list->clear(ec); setDOMException(exec, ec); - m_context->svgAttributeChanged(imp->associatedAttributeName()); + JSSVGContextCache::propagateSVGDOMChange(this, list->associatedAttributeName()); return jsUndefined(); } @@ -53,14 +54,15 @@ JSValue JSSVGPathSegList::initialize(ExecState* exec, const ArgList& args) ExceptionCode ec = 0; SVGPathSeg* newItem = toSVGPathSeg(args.at(0)); - SVGPathSegList* imp = static_cast<SVGPathSegList*>(impl()); + SVGPathSegList* list = impl(); - SVGPathSeg* obj = WTF::getPtr(imp->initialize(newItem, ec)); + SVGPathSeg* obj = WTF::getPtr(list->initialize(newItem, ec)); + SVGElement* context = JSSVGContextCache::svgContextForDOMObject(this); - JSC::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), obj, m_context.get()); + JSValue result = toJS(exec, globalObject(), obj, context); setDOMException(exec, ec); - m_context->svgAttributeChanged(imp->associatedAttributeName()); + JSSVGContextCache::propagateSVGDOMChange(this, list->associatedAttributeName()); return result; } @@ -75,10 +77,11 @@ JSValue JSSVGPathSegList::getItem(ExecState* exec, const ArgList& args) return jsUndefined(); } - SVGPathSegList* imp = static_cast<SVGPathSegList*>(impl()); - SVGPathSeg* obj = WTF::getPtr(imp->getItem(index, ec)); + SVGPathSegList* list = impl(); + SVGPathSeg* obj = WTF::getPtr(list->getItem(index, ec)); + SVGElement* context = JSSVGContextCache::svgContextForDOMObject(this); - JSC::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), obj, m_context.get()); + JSValue result = toJS(exec, globalObject(), obj, context); setDOMException(exec, ec); return result; } @@ -95,12 +98,13 @@ JSValue JSSVGPathSegList::insertItemBefore(ExecState* exec, const ArgList& args) return jsUndefined(); } - SVGPathSegList* imp = static_cast<SVGPathSegList*>(impl()); + SVGPathSegList* list = impl(); + SVGElement* context = JSSVGContextCache::svgContextForDOMObject(this); - JSC::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), WTF::getPtr(imp->insertItemBefore(newItem, index, ec)), m_context.get()); + JSValue result = toJS(exec, globalObject(), WTF::getPtr(list->insertItemBefore(newItem, index, ec)), context); setDOMException(exec, ec); - m_context->svgAttributeChanged(imp->associatedAttributeName()); + JSSVGContextCache::propagateSVGDOMChange(this, list->associatedAttributeName()); return result; } @@ -116,12 +120,13 @@ JSValue JSSVGPathSegList::replaceItem(ExecState* exec, const ArgList& args) return jsUndefined(); } - SVGPathSegList* imp = static_cast<SVGPathSegList*>(impl()); + SVGPathSegList* list = impl(); + SVGElement* context = JSSVGContextCache::svgContextForDOMObject(this); - JSC::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), WTF::getPtr(imp->replaceItem(newItem, index, ec)), m_context.get()); + JSValue result = toJS(exec, globalObject(), WTF::getPtr(list->replaceItem(newItem, index, ec)), context); setDOMException(exec, ec); - m_context->svgAttributeChanged(imp->associatedAttributeName()); + JSSVGContextCache::propagateSVGDOMChange(this, list->associatedAttributeName()); return result; } @@ -136,14 +141,15 @@ JSValue JSSVGPathSegList::removeItem(ExecState* exec, const ArgList& args) return jsUndefined(); } - SVGPathSegList* imp = static_cast<SVGPathSegList*>(impl()); + SVGPathSegList* list = impl(); - RefPtr<SVGPathSeg> obj(imp->removeItem(index, ec)); + RefPtr<SVGPathSeg> obj(list->removeItem(index, ec)); + SVGElement* context = JSSVGContextCache::svgContextForDOMObject(this); - JSC::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), obj.get(), m_context.get()); + JSValue result = toJS(exec, globalObject(), obj.get(), context); setDOMException(exec, ec); - m_context->svgAttributeChanged(imp->associatedAttributeName()); + JSSVGContextCache::propagateSVGDOMChange(this, list->associatedAttributeName()); return result; } @@ -152,12 +158,13 @@ JSValue JSSVGPathSegList::appendItem(ExecState* exec, const ArgList& args) ExceptionCode ec = 0; SVGPathSeg* newItem = toSVGPathSeg(args.at(0)); - SVGPathSegList* imp = static_cast<SVGPathSegList*>(impl()); + SVGPathSegList* list = impl(); + SVGElement* context = JSSVGContextCache::svgContextForDOMObject(this); - JSC::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), WTF::getPtr(imp->appendItem(newItem, ec)), m_context.get()); + JSValue result = toJS(exec, globalObject(), WTF::getPtr(list->appendItem(newItem, ec)), context); setDOMException(exec, ec); - m_context->svgAttributeChanged(imp->associatedAttributeName()); + JSSVGContextCache::propagateSVGDOMChange(this, list->associatedAttributeName()); return result; } diff --git a/WebCore/bindings/js/JSSVGPointListCustom.cpp b/WebCore/bindings/js/JSSVGPointListCustom.cpp deleted file mode 100644 index 1969fe2..0000000 --- a/WebCore/bindings/js/JSSVGPointListCustom.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> - * Copyright (C) 2008 Apple Inc. All rights reserved. - * - * 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" - -#if ENABLE(SVG) -#include "JSSVGPointList.h" - -#include "JSSVGPoint.h" -#include "SVGPointList.h" - -using namespace JSC; - -namespace WebCore { - -typedef SVGPODListItem<FloatPoint> PODListItem; -typedef SVGList<RefPtr<PODListItem> > SVGPointListBase; - -static JSValue finishGetter(ExecState* exec, ExceptionCode& ec, SVGElement* context, SVGPointList* list, PassRefPtr<PODListItem > item) -{ - if (ec) { - setDOMException(exec, ec); - return jsUndefined(); - } - return toJS(exec, deprecatedGlobalObjectForPrototype(exec), JSSVGPODTypeWrapperCreatorForList<FloatPoint>::create(item.get(), list->associatedAttributeName()).get(), context); -} - -static JSValue finishSetter(ExecState* exec, ExceptionCode& ec, SVGElement* context, SVGPointList* list, PassRefPtr<PODListItem > item) -{ - if (ec) { - setDOMException(exec, ec); - return jsUndefined(); - } - const QualifiedName& attributeName = list->associatedAttributeName(); - context->svgAttributeChanged(attributeName); - return toJS(exec, deprecatedGlobalObjectForPrototype(exec), JSSVGPODTypeWrapperCreatorForList<FloatPoint>::create(item.get(), attributeName).get(), context); -} - -static JSValue finishSetterReadOnlyResult(ExecState* exec, ExceptionCode& ec, SVGElement* context, SVGPointList* list, PassRefPtr<PODListItem> item) -{ - if (ec) { - setDOMException(exec, ec); - return jsUndefined(); - } - context->svgAttributeChanged(list->associatedAttributeName()); - return toJS(exec, deprecatedGlobalObjectForPrototype(exec), JSSVGStaticPODTypeWrapper<FloatPoint>::create(*item).get(), context); -} - -JSValue JSSVGPointList::clear(ExecState* exec, const ArgList&) -{ - ExceptionCode ec = 0; - impl()->clear(ec); - setDOMException(exec, ec); - m_context->svgAttributeChanged(impl()->associatedAttributeName()); - return jsUndefined(); -} - -JSValue JSSVGPointList::initialize(ExecState* exec, const ArgList& args) -{ - ExceptionCode ec = 0; - SVGPointListBase* listImp = impl(); - return finishSetter(exec, ec, context(), impl(), - listImp->initialize(PODListItem::copy(toSVGPoint(args.at(0))), ec)); -} - -JSValue JSSVGPointList::getItem(ExecState* exec, const ArgList& args) -{ - bool indexOk; - unsigned index = args.at(0).toUInt32(exec, indexOk); - if (!indexOk) { - setDOMException(exec, TYPE_MISMATCH_ERR); - return jsUndefined(); - } - - ExceptionCode ec = 0; - SVGPointListBase* listImp = impl(); - return finishGetter(exec, ec, context(), impl(), - listImp->getItem(index, ec)); -} - -JSValue JSSVGPointList::insertItemBefore(ExecState* exec, const ArgList& args) -{ - bool indexOk; - unsigned index = args.at(1).toUInt32(exec, indexOk); - if (!indexOk) { - setDOMException(exec, TYPE_MISMATCH_ERR); - return jsUndefined(); - } - - ExceptionCode ec = 0; - SVGPointListBase* listImp = impl(); - return finishSetter(exec, ec, context(), impl(), - listImp->insertItemBefore(PODListItem::copy(toSVGPoint(args.at(0))), index, ec)); -} - -JSValue JSSVGPointList::replaceItem(ExecState* exec, const ArgList& args) -{ - bool indexOk; - unsigned index = args.at(1).toInt32(exec, indexOk); - if (!indexOk) { - setDOMException(exec, TYPE_MISMATCH_ERR); - return jsUndefined(); - } - - ExceptionCode ec = 0; - SVGPointListBase* listImp = impl(); - return finishSetter(exec, ec, context(), impl(), - listImp->replaceItem(PODListItem::copy(toSVGPoint(args.at(0))), index, ec)); -} - -JSValue JSSVGPointList::removeItem(ExecState* exec, const ArgList& args) -{ - bool indexOk; - unsigned index = args.at(0).toInt32(exec, indexOk); - if (!indexOk) { - setDOMException(exec, TYPE_MISMATCH_ERR); - return jsUndefined(); - } - - ExceptionCode ec = 0; - SVGPointListBase* listImp = impl(); - return finishSetterReadOnlyResult(exec, ec, context(), impl(), - listImp->removeItem(index, ec)); -} - -JSValue JSSVGPointList::appendItem(ExecState* exec, const ArgList& args) -{ - ExceptionCode ec = 0; - SVGPointListBase* listImp = impl(); - return finishSetter(exec, ec, context(), impl(), - listImp->appendItem(PODListItem::copy(toSVGPoint(args.at(0))), ec)); -} - -} - -#endif // ENABLE(SVG) diff --git a/WebCore/bindings/js/JSSVGTransformListCustom.cpp b/WebCore/bindings/js/JSSVGTransformListCustom.cpp deleted file mode 100644 index 1a9110a..0000000 --- a/WebCore/bindings/js/JSSVGTransformListCustom.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> - * Copyright (C) 2008 Apple Inc. All rights reserved. - * - * 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" - -#if ENABLE(SVG) -#include "JSSVGTransformList.h" - -#include "JSSVGTransform.h" -#include "SVGTransformList.h" - -using namespace JSC; - -namespace WebCore { - -typedef SVGPODListItem<SVGTransform> PODListItem; -typedef SVGList<RefPtr<PODListItem> > SVGTransformListBase; - -static JSValue finishGetter(ExecState* exec, ExceptionCode& ec, SVGElement* context, SVGTransformList* list, PassRefPtr<PODListItem> item) -{ - if (ec) { - setDOMException(exec, ec); - return jsUndefined(); - } - return toJS(exec, deprecatedGlobalObjectForPrototype(exec), JSSVGPODTypeWrapperCreatorForList<SVGTransform>::create(item.get(), list->associatedAttributeName()).get(), context); -} - -static JSValue finishSetter(ExecState* exec, ExceptionCode& ec, SVGElement* context, SVGTransformList* list, PassRefPtr<PODListItem> item) -{ - if (ec) { - setDOMException(exec, ec); - return jsUndefined(); - } - const QualifiedName& attributeName = list->associatedAttributeName(); - context->svgAttributeChanged(attributeName); - return toJS(exec, deprecatedGlobalObjectForPrototype(exec), JSSVGPODTypeWrapperCreatorForList<SVGTransform>::create(item.get(), attributeName).get(), context); -} - -static JSValue finishSetterReadOnlyResult(ExecState* exec, ExceptionCode& ec, SVGElement* context, SVGTransformList* list, PassRefPtr<PODListItem> item) -{ - if (ec) { - setDOMException(exec, ec); - return jsUndefined(); - } - context->svgAttributeChanged(list->associatedAttributeName()); - return toJS(exec, deprecatedGlobalObjectForPrototype(exec), JSSVGStaticPODTypeWrapper<SVGTransform>::create(*item).get(), context); -} - -JSValue JSSVGTransformList::clear(ExecState* exec, const ArgList&) -{ - ExceptionCode ec = 0; - impl()->clear(ec); - setDOMException(exec, ec); - m_context->svgAttributeChanged(impl()->associatedAttributeName()); - return jsUndefined(); -} - -JSValue JSSVGTransformList::initialize(ExecState* exec, const ArgList& args) -{ - ExceptionCode ec = 0; - SVGTransformListBase* listImp = impl(); - return finishSetter(exec, ec, context(), impl(), - listImp->initialize(PODListItem::copy(toSVGTransform(args.at(0))), ec)); -} - -JSValue JSSVGTransformList::getItem(ExecState* exec, const ArgList& args) -{ - bool indexOk; - unsigned index = args.at(0).toUInt32(exec, indexOk); - if (!indexOk) { - setDOMException(exec, TYPE_MISMATCH_ERR); - return jsUndefined(); - } - - ExceptionCode ec = 0; - SVGTransformListBase* listImp = impl(); - return finishGetter(exec, ec, context(), impl(), - listImp->getItem(index, ec)); -} - -JSValue JSSVGTransformList::insertItemBefore(ExecState* exec, const ArgList& args) -{ - bool indexOk; - unsigned index = args.at(1).toUInt32(exec, indexOk); - if (!indexOk) { - setDOMException(exec, TYPE_MISMATCH_ERR); - return jsUndefined(); - } - - ExceptionCode ec = 0; - SVGTransformListBase* listImp = impl(); - return finishSetter(exec, ec, context(), impl(), - listImp->insertItemBefore(PODListItem::copy(toSVGTransform(args.at(0))), index, ec)); -} - -JSValue JSSVGTransformList::replaceItem(ExecState* exec, const ArgList& args) -{ - bool indexOk; - unsigned index = args.at(1).toUInt32(exec, indexOk); - if (!indexOk) { - setDOMException(exec, TYPE_MISMATCH_ERR); - return jsUndefined(); - } - - ExceptionCode ec = 0; - SVGTransformListBase* listImp = impl(); - return finishSetter(exec, ec, context(), impl(), - listImp->replaceItem(PODListItem::copy(toSVGTransform(args.at(0))), index, ec)); -} - -JSValue JSSVGTransformList::removeItem(ExecState* exec, const ArgList& args) -{ - bool indexOk; - unsigned index = args.at(0).toUInt32(exec, indexOk); - if (!indexOk) { - setDOMException(exec, TYPE_MISMATCH_ERR); - return jsUndefined(); - } - - ExceptionCode ec = 0; - SVGTransformListBase* listImp = impl(); - return finishSetterReadOnlyResult(exec, ec, context(), impl(), - listImp->removeItem(index, ec)); -} - -JSValue JSSVGTransformList::appendItem(ExecState* exec, const ArgList& args) -{ - ExceptionCode ec = 0; - SVGTransformListBase* listImp = impl(); - return finishSetter(exec, ec, context(), impl(), - listImp->appendItem(PODListItem::copy(toSVGTransform(args.at(0))), ec)); -} - -} - -#endif // ENABLE(SVG) diff --git a/WebCore/bindings/js/JSStorageCustom.cpp b/WebCore/bindings/js/JSStorageCustom.cpp index e416d35..3cfe22e 100644 --- a/WebCore/bindings/js/JSStorageCustom.cpp +++ b/WebCore/bindings/js/JSStorageCustom.cpp @@ -64,13 +64,13 @@ bool JSStorage::deleteProperty(ExecState* exec, const Identifier& propertyName) return true; } -void JSStorage::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSStorage::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { unsigned length = m_impl->length(); for (unsigned i = 0; i < length; ++i) propertyNames.add(Identifier(exec, m_impl->key(i))); - Base::getOwnPropertyNames(exec, propertyNames); + Base::getOwnPropertyNames(exec, propertyNames, mode); } bool JSStorage::putDelegate(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot&) diff --git a/WebCore/bindings/js/JSWebGLArrayHelper.h b/WebCore/bindings/js/JSWebGLArrayHelper.h index f538cce..3326d76 100644 --- a/WebCore/bindings/js/JSWebGLArrayHelper.h +++ b/WebCore/bindings/js/JSWebGLArrayHelper.h @@ -27,6 +27,8 @@ #ifndef JSWebGLArrayHelper_h #define JSWebGLArrayHelper_h +#include "ExceptionCode.h" +#include "JSDOMBinding.h" #include <interpreter/CallFrame.h> #include <runtime/ArgList.h> #include <runtime/Error.h> @@ -45,11 +47,15 @@ JSC::JSValue setWebGLArrayFromArray(JSC::ExecState* exec, T* webGLArray, JSC::Ar if (args.size() == 2) offset = args.at(1).toInt32(exec); int length = array->get(exec, JSC::Identifier(exec, "length")).toInt32(exec); - for (int i = 0; i < length; i++) { - JSC::JSValue v = array->get(exec, i); - if (exec->hadException()) - return JSC::jsUndefined(); - webGLArray->set(i + offset, v.toNumber(exec)); + if (offset + length > webGLArray->length()) + setDOMException(exec, INDEX_SIZE_ERR); + else { + for (int i = 0; i < length; i++) { + JSC::JSValue v = array->get(exec, i); + if (exec->hadException()) + return JSC::jsUndefined(); + webGLArray->set(i + offset, v.toNumber(exec)); + } } return JSC::jsUndefined(); diff --git a/WebCore/bindings/js/JSWebGLFloatArrayCustom.cpp b/WebCore/bindings/js/JSWebGLFloatArrayCustom.cpp index 5f5b24f..f4acbcf 100644 --- a/WebCore/bindings/js/JSWebGLFloatArrayCustom.cpp +++ b/WebCore/bindings/js/JSWebGLFloatArrayCustom.cpp @@ -38,7 +38,7 @@ namespace WebCore { void JSWebGLFloatArray::indexSetter(JSC::ExecState* exec, unsigned index, JSC::JSValue value) { - impl()->set(index, static_cast<float>(value.toInt32(exec))); + impl()->set(index, static_cast<float>(value.toNumber(exec))); } JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, WebGLFloatArray* object) @@ -52,9 +52,9 @@ JSC::JSValue JSWebGLFloatArray::set(JSC::ExecState* exec, JSC::ArgList const& ar return throwError(exec, SyntaxError); if (args.size() == 2 && args.at(0).isInt32()) { - // void set(in unsigned long index, in long value); + // void set(in unsigned long index, in float value); unsigned index = args.at(0).toUInt32(exec); - impl()->set(index, static_cast<signed char>(args.at(1).toInt32(exec))); + impl()->set(index, static_cast<float>(args.at(1).toNumber(exec))); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSWebGLIntArrayCustom.cpp b/WebCore/bindings/js/JSWebGLIntArrayCustom.cpp index 9c384d8..de08256 100644 --- a/WebCore/bindings/js/JSWebGLIntArrayCustom.cpp +++ b/WebCore/bindings/js/JSWebGLIntArrayCustom.cpp @@ -54,7 +54,7 @@ JSC::JSValue JSWebGLIntArray::set(JSC::ExecState* exec, JSC::ArgList const& args if (args.size() == 2 && args.at(0).isInt32()) { // void set(in unsigned long index, in long value); unsigned index = args.at(0).toUInt32(exec); - impl()->set(index, static_cast<signed char>(args.at(1).toInt32(exec))); + impl()->set(index, static_cast<signed int>(args.at(1).toInt32(exec))); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSWebGLRenderingContextCustom.cpp b/WebCore/bindings/js/JSWebGLRenderingContextCustom.cpp index 3de9606..e336027 100644 --- a/WebCore/bindings/js/JSWebGLRenderingContextCustom.cpp +++ b/WebCore/bindings/js/JSWebGLRenderingContextCustom.cpp @@ -29,12 +29,14 @@ #include "JSWebGLRenderingContext.h" -#include "WebGLRenderingContext.h" #include "ExceptionCode.h" #include "HTMLCanvasElement.h" #include "HTMLImageElement.h" +#include "HTMLVideoElement.h" #include "JSHTMLCanvasElement.h" #include "JSHTMLImageElement.h" +#include "JSHTMLVideoElement.h" +#include "JSImageData.h" #include "JSWebGLBuffer.h" #include "JSWebGLFloatArray.h" #include "JSWebGLFramebuffer.h" @@ -48,11 +50,12 @@ #include "JSWebKitCSSMatrix.h" #include "NotImplemented.h" #include "WebGLBuffer.h" -#include "WebGLGetInfo.h" #include "WebGLFloatArray.h" #include "WebGLFramebuffer.h" +#include "WebGLGetInfo.h" #include "WebGLIntArray.h" #include "WebGLProgram.h" +#include "WebGLRenderingContext.h" #include <runtime/Error.h> #include <wtf/FastMalloc.h> #include <wtf/OwnFastMallocPtr.h> @@ -79,8 +82,7 @@ JSValue JSWebGLRenderingContext::bufferData(JSC::ExecState* exec, JSC::ArgList c static_cast<WebGLRenderingContext*>(impl())->bufferData(target, array, usage, ec); } - if (ec != 0) - setDOMException(exec, ec); + setDOMException(exec, ec); return jsUndefined(); } @@ -97,8 +99,7 @@ JSValue JSWebGLRenderingContext::bufferSubData(JSC::ExecState* exec, JSC::ArgLis static_cast<WebGLRenderingContext*>(impl())->bufferSubData(target, offset, array, ec); - if (ec != 0) - setDOMException(exec, ec); + setDOMException(exec, ec); return jsUndefined(); } @@ -307,27 +308,60 @@ JSValue JSWebGLRenderingContext::getVertexAttrib(ExecState* exec, const ArgList& return getObjectParameter(this, exec, args, kVertexAttrib); } -// void texImage2DHTML(in unsigned long target, in unsigned long level, in HTMLImageElement image); +// void texImage2D(in GLenum target, in GLint level, in GLenum internalformat, in GLsizei width, in GLsizei height, in GLint border, in GLenum format, in GLenum type, in WebGLArray pixels); +// void texImage2D(in GLenum target, in GLint level, in ImageData pixels, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha); +// void texImage2D(in GLenum target, in GLint level, in HTMLImageElement image, [Optional] in GLboolean flipY, [Optional] in premultiplyAlpha); +// void texImage2D(in GLenum target, in GLint level, in HTMLCanvasElement canvas, [Optional] in GLboolean flipY, [Optional] in premultiplyAlpha); +// void texImage2D(in GLenum target, in GLint level, in HTMLVideoElement video, [Optional] in GLboolean flipY, [Optional] in premultiplyAlpha); JSValue JSWebGLRenderingContext::texImage2D(ExecState* exec, const ArgList& args) { - if (args.size() < 3) + if (args.size() < 3 || args.size() > 9) return throwError(exec, SyntaxError); ExceptionCode ec = 0; + WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(impl()); unsigned target = args.at(0).toInt32(exec); if (exec->hadException()) return jsUndefined(); - + unsigned level = args.at(1).toInt32(exec); if (exec->hadException()) return jsUndefined(); + + JSObject* o = 0; + + if (args.size() <= 5) { + // This is one of the last 4 forms. Param 2 can be ImageData or <img>, <canvas> or <video> element. + JSValue value = args.at(2); - if (args.size() > 5) { - // This must be the bare array case. + if (!value.isObject()) + return throwError(exec, TypeError); + + o = asObject(value); + + bool flipY = args.at(3).toBoolean(exec); + bool premultiplyAlpha = args.at(4).toBoolean(exec); + + if (o->inherits(&JSImageData::s_info)) { + ImageData* data = static_cast<ImageData*>(static_cast<JSImageData*>(o)->impl()); + context->texImage2D(target, level, data, flipY, premultiplyAlpha, ec); + } else if (o->inherits(&JSHTMLImageElement::s_info)) { + HTMLImageElement* element = static_cast<HTMLImageElement*>(static_cast<JSHTMLImageElement*>(o)->impl()); + context->texImage2D(target, level, element, flipY, premultiplyAlpha, ec); + } else if (o->inherits(&JSHTMLCanvasElement::s_info)) { + HTMLCanvasElement* element = static_cast<HTMLCanvasElement*>(static_cast<JSHTMLCanvasElement*>(o)->impl()); + context->texImage2D(target, level, element, flipY, premultiplyAlpha, ec); + } else if (o->inherits(&JSHTMLVideoElement::s_info)) { + HTMLVideoElement* element = static_cast<HTMLVideoElement*>(static_cast<JSHTMLVideoElement*>(o)->impl()); + context->texImage2D(target, level, element, flipY, premultiplyAlpha, ec); + } else + ec = TYPE_MISMATCH_ERR; + } else { if (args.size() != 9) return throwError(exec, SyntaxError); - + + // This must be the WebGLArray case unsigned internalformat = args.at(2).toInt32(exec); if (exec->hadException()) return jsUndefined(); @@ -352,104 +386,143 @@ JSValue JSWebGLRenderingContext::texImage2D(ExecState* exec, const ArgList& args if (exec->hadException()) return jsUndefined(); - WebGLArray* array = toWebGLArray(args.at(8)); - if (exec->hadException()) - return jsUndefined(); + JSValue value = args.at(8); - if (!array) + // For this case passing 0 (for a null array) is allowed + if (value.isNull()) + context->texImage2D(target, level, internalformat, width, height, border, format, type, 0, ec); + else if (value.isObject()) { + o = asObject(value); + + if (o->inherits(&JSWebGLArray::s_info)) { + // FIXME: Need to check to make sure WebGLArray is a WebGLByteArray or WebGLShortArray, + // depending on the passed type parameter. + WebGLArray* obj = static_cast<WebGLArray*>(static_cast<JSWebGLArray*>(o)->impl()); + context->texImage2D(target, level, internalformat, width, height, border, format, type, obj, ec); + } else + return throwError(exec, TypeError); + } else return throwError(exec, TypeError); - - // FIXME: Need to check to make sure WebGLArray is a WebGLByteArray or WebGLShortArray, - // depending on the passed type parameter. - - context->texImage2D(target, level, internalformat, width, height, border, format, type, array, ec); - return jsUndefined(); - } - - // The image parameter can be a <img> or <canvas> element. - JSValue value = args.at(2); - if (!value.isObject()) - return throwError(exec, TypeError); - JSObject* o = asObject(value); - - bool flipY = (args.size() > 3) ? args.at(3).toBoolean(exec) : false; - bool premultiplyAlpha = (args.size() > 4) ? args.at(3).toBoolean(exec) : false; - - if (o->inherits(&JSHTMLImageElement::s_info)) { - HTMLImageElement* imgElt = static_cast<HTMLImageElement*>(static_cast<JSHTMLElement*>(o)->impl()); - context->texImage2D(target, level, imgElt, flipY, premultiplyAlpha, ec); - } else if (o->inherits(&JSHTMLCanvasElement::s_info)) { - HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(static_cast<JSHTMLElement*>(o)->impl()); - context->texImage2D(target, level, canvas, flipY, premultiplyAlpha, ec); - } else { - setDOMException(exec, TYPE_MISMATCH_ERR); } + setDOMException(exec, ec); return jsUndefined(); } -// void texSubImage2DHTML(in unsigned long target, in unsigned long level, in unsigned long xoff, in unsigned long yoff, in unsigned long width, in unsigned long height, in HTMLImageElement image); +// void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, in GLsizei width, in GLsizei height, in GLenum format, in GLenum type, in WebGLArray pixels); +// void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, in ImageData pixels, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha); +// void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, in HTMLImageElement image, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha); +// void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, in HTMLCanvasElement canvas, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha); +// void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, in HTMLVideoElement video, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha); JSValue JSWebGLRenderingContext::texSubImage2D(ExecState* exec, const ArgList& args) { - if (args.size() < 7 || args.size() > 9) + if (args.size() < 5 || args.size() > 9) return throwError(exec, SyntaxError); + ExceptionCode ec = 0; + WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(impl()); unsigned target = args.at(0).toInt32(exec); + if (exec->hadException()) + return jsUndefined(); + unsigned level = args.at(1).toInt32(exec); - unsigned xoff = args.at(2).toInt32(exec); - unsigned yoff = args.at(3).toInt32(exec); - unsigned width = args.at(4).toInt32(exec); - unsigned height = args.at(5).toInt32(exec); + if (exec->hadException()) + return jsUndefined(); - // The image parameter can be a <img> or <canvas> element. - JSValue value = args.at(6); - if (!value.isObject()) - return throwError(exec, TypeError); - JSObject* o = asObject(value); + unsigned xoff = args.at(2).toInt32(exec); + if (exec->hadException()) + return jsUndefined(); - bool flipY = (args.size() > 3) ? args.at(3).toBoolean(exec) : false; - bool premultiplyAlpha = (args.size() > 4) ? args.at(3).toBoolean(exec) : false; + unsigned yoff = args.at(3).toInt32(exec); + if (exec->hadException()) + return jsUndefined(); - ExceptionCode ec = 0; - if (o->inherits(&JSHTMLImageElement::s_info)) { - HTMLImageElement* imgElt = static_cast<HTMLImageElement*>(static_cast<JSHTMLElement*>(o)->impl()); - context->texSubImage2D(target, level, xoff, yoff, width, height, imgElt, flipY, premultiplyAlpha, ec); - } else if (o->inherits(&JSHTMLCanvasElement::s_info)) { - HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(static_cast<JSHTMLElement*>(o)->impl()); - context->texSubImage2D(target, level, xoff, yoff, width, height, canvas, flipY, premultiplyAlpha, ec); - } else - ec = TYPE_MISMATCH_ERR; + JSObject* o = 0; + + if (args.size() <= 7) { + // This is one of the last 4 forms. Param 4 can be <img>, <canvas> or <video> element, of the format param. + JSValue value = args.at(4); + + if (!value.isObject()) + return throwError(exec, SyntaxError); + + o = asObject(value); + + bool flipY = args.at(5).toBoolean(exec); + bool premultiplyAlpha = args.at(6).toBoolean(exec); + + if (o->inherits(&JSImageData::s_info)) { + ImageData* data = static_cast<ImageData*>(static_cast<JSImageData*>(o)->impl()); + context->texSubImage2D(target, level, xoff, yoff, data, flipY, premultiplyAlpha, ec); + } else if (o->inherits(&JSHTMLImageElement::s_info)) { + HTMLImageElement* element = static_cast<HTMLImageElement*>(static_cast<JSHTMLImageElement*>(o)->impl()); + context->texSubImage2D(target, level, xoff, yoff, element, flipY, premultiplyAlpha, ec); + } else if (o->inherits(&JSHTMLCanvasElement::s_info)) { + HTMLCanvasElement* element = static_cast<HTMLCanvasElement*>(static_cast<JSHTMLCanvasElement*>(o)->impl()); + context->texSubImage2D(target, level, xoff, yoff, element, flipY, premultiplyAlpha, ec); + } else if (o->inherits(&JSHTMLVideoElement::s_info)) { + HTMLVideoElement* element = static_cast<HTMLVideoElement*>(static_cast<JSHTMLVideoElement*>(o)->impl()); + context->texSubImage2D(target, level, xoff, yoff, element, flipY, premultiplyAlpha, ec); + } else + ec = TYPE_MISMATCH_ERR; + } else { + // This must be the WebGLArray form + if (args.size() != 9) + return throwError(exec, SyntaxError); + + unsigned width = args.at(4).toInt32(exec); + if (exec->hadException()) + return jsUndefined(); + + unsigned height = args.at(5).toInt32(exec); + if (exec->hadException()) + return jsUndefined(); + + unsigned format = args.at(6).toInt32(exec); + if (exec->hadException()) + return jsUndefined(); + + unsigned type = args.at(7).toInt32(exec); + if (exec->hadException()) + return jsUndefined(); + + JSValue value = args.at(8); + if (!value.isObject()) + context->texSubImage2D(target, level, xoff, yoff, width, height, format, type, 0, ec); + else { + o = asObject(value); + + if (o->inherits(&JSWebGLArray::s_info)) { + WebGLArray* obj = static_cast<WebGLArray*>(static_cast<JSWebGLArray*>(o)->impl()); + context->texSubImage2D(target, level, xoff, yoff, width, height, format, type, obj, ec); + } else + return throwError(exec, TypeError); + } + } - if (ec != 0) - setDOMException(exec, ec); - return jsUndefined(); + setDOMException(exec, ec); + return jsUndefined(); } -template<typename T> -void toArray(JSC::ExecState* exec, JSC::JSValue value, T*& array, int& size) +template<typename T, size_t inlineCapacity> +bool toVector(JSC::ExecState* exec, JSC::JSValue value, Vector<T, inlineCapacity>& vector) { - array = 0; - if (!value.isObject()) - return; - + return false; + JSC::JSObject* object = asObject(value); - int length = object->get(exec, JSC::Identifier(exec, "length")).toInt32(exec); - void* tempValues; - if (!tryFastMalloc(length * sizeof(T)).getValue(tempValues)) - return; - - T* values = static_cast<T*>(tempValues); - for (int i = 0; i < length; ++i) { + int32_t length = object->get(exec, JSC::Identifier(exec, "length")).toInt32(exec); + vector.resize(length); + + for (int32_t i = 0; i < length; ++i) { JSC::JSValue v = object->get(exec, i); if (exec->hadException()) - return; - values[i] = static_cast<T>(v.toNumber(exec)); + return false; + vector[i] = static_cast<T>(v.toNumber(exec)); } - array = values; - size = length; + return true; } enum DataFunctionToCall { @@ -497,40 +570,69 @@ static JSC::JSValue dataFunctionf(DataFunctionToCall f, JSC::ExecState* exec, co ExceptionCode ec = 0; if (webGLArray) { - switch(f) { - case f_uniform1v: context->uniform1fv(location, webGLArray.get(), ec); break; - case f_uniform2v: context->uniform2fv(location, webGLArray.get(), ec); break; - case f_uniform3v: context->uniform3fv(location, webGLArray.get(), ec); break; - case f_uniform4v: context->uniform4fv(location, webGLArray.get(), ec); break; - case f_vertexAttrib1v: context->vertexAttrib1fv(index, webGLArray.get()); break; - case f_vertexAttrib2v: context->vertexAttrib2fv(index, webGLArray.get()); break; - case f_vertexAttrib3v: context->vertexAttrib3fv(index, webGLArray.get()); break; - case f_vertexAttrib4v: context->vertexAttrib4fv(index, webGLArray.get()); break; + switch (f) { + case f_uniform1v: + context->uniform1fv(location, webGLArray.get(), ec); + break; + case f_uniform2v: + context->uniform2fv(location, webGLArray.get(), ec); + break; + case f_uniform3v: + context->uniform3fv(location, webGLArray.get(), ec); + break; + case f_uniform4v: + context->uniform4fv(location, webGLArray.get(), ec); + break; + case f_vertexAttrib1v: + context->vertexAttrib1fv(index, webGLArray.get()); + break; + case f_vertexAttrib2v: + context->vertexAttrib2fv(index, webGLArray.get()); + break; + case f_vertexAttrib3v: + context->vertexAttrib3fv(index, webGLArray.get()); + break; + case f_vertexAttrib4v: + context->vertexAttrib4fv(index, webGLArray.get()); + break; } - if (ec != 0) - setDOMException(exec, ec); + + setDOMException(exec, ec); return jsUndefined(); } - - float* array; - int size; - toArray<float>(exec, args.at(1), array, size); - - if (!array) + + Vector<float, 64> array; + if (!toVector(exec, args.at(1), array)) return throwError(exec, TypeError); - switch(f) { - case f_uniform1v: context->uniform1fv(location, array, size, ec); break; - case f_uniform2v: context->uniform2fv(location, array, size, ec); break; - case f_uniform3v: context->uniform3fv(location, array, size, ec); break; - case f_uniform4v: context->uniform4fv(location, array, size, ec); break; - case f_vertexAttrib1v: context->vertexAttrib1fv(index, array, size); break; - case f_vertexAttrib2v: context->vertexAttrib2fv(index, array, size); break; - case f_vertexAttrib3v: context->vertexAttrib3fv(index, array, size); break; - case f_vertexAttrib4v: context->vertexAttrib4fv(index, array, size); break; + switch (f) { + case f_uniform1v: + context->uniform1fv(location, array.data(), array.size(), ec); + break; + case f_uniform2v: + context->uniform2fv(location, array.data(), array.size(), ec); + break; + case f_uniform3v: + context->uniform3fv(location, array.data(), array.size(), ec); + break; + case f_uniform4v: + context->uniform4fv(location, array.data(), array.size(), ec); + break; + case f_vertexAttrib1v: + context->vertexAttrib1fv(index, array.data(), array.size()); + break; + case f_vertexAttrib2v: + context->vertexAttrib2fv(index, array.data(), array.size()); + break; + case f_vertexAttrib3v: + context->vertexAttrib3fv(index, array.data(), array.size()); + break; + case f_vertexAttrib4v: + context->vertexAttrib4fv(index, array.data(), array.size()); + break; } - if (ec != 0) - setDOMException(exec, ec); + + setDOMException(exec, ec); return jsUndefined(); } @@ -550,34 +652,50 @@ static JSC::JSValue dataFunctioni(DataFunctionToCall f, JSC::ExecState* exec, co ExceptionCode ec = 0; if (webGLArray) { - switch(f) { - case f_uniform1v: context->uniform1iv(location, webGLArray.get(), ec); break; - case f_uniform2v: context->uniform2iv(location, webGLArray.get(), ec); break; - case f_uniform3v: context->uniform3iv(location, webGLArray.get(), ec); break; - case f_uniform4v: context->uniform4iv(location, webGLArray.get(), ec); break; - default: break; + switch (f) { + case f_uniform1v: + context->uniform1iv(location, webGLArray.get(), ec); + break; + case f_uniform2v: + context->uniform2iv(location, webGLArray.get(), ec); + break; + case f_uniform3v: + context->uniform3iv(location, webGLArray.get(), ec); + break; + case f_uniform4v: + context->uniform4iv(location, webGLArray.get(), ec); + break; + default: + break; } - if (ec != 0) - setDOMException(exec, ec); + + setDOMException(exec, ec); return jsUndefined(); } - - int* array; - int size; - toArray<int>(exec, args.at(1), array, size); - - if (!array) + + + Vector<int, 64> array; + if (!toVector(exec, args.at(1), array)) return throwError(exec, TypeError); - switch(f) { - case f_uniform1v: context->uniform1iv(location, array, size, ec); break; - case f_uniform2v: context->uniform2iv(location, array, size, ec); break; - case f_uniform3v: context->uniform3iv(location, array, size, ec); break; - case f_uniform4v: context->uniform4iv(location, array, size, ec); break; - default: break; + switch (f) { + case f_uniform1v: + context->uniform1iv(location, array.data(), array.size(), ec); + break; + case f_uniform2v: + context->uniform2iv(location, array.data(), array.size(), ec); + break; + case f_uniform3v: + context->uniform3iv(location, array.data(), array.size(), ec); + break; + case f_uniform4v: + context->uniform4iv(location, array.data(), array.size(), ec); + break; + default: + break; } - if (ec != 0) - setDOMException(exec, ec); + + setDOMException(exec, ec); return jsUndefined(); } @@ -601,30 +719,39 @@ static JSC::JSValue dataFunctionMatrix(DataFunctionMatrixToCall f, JSC::ExecStat ExceptionCode ec = 0; if (webGLArray) { - switch(f) { - case f_uniformMatrix2fv: context->uniformMatrix2fv(location, transpose, webGLArray.get(), ec); break; - case f_uniformMatrix3fv: context->uniformMatrix3fv(location, transpose, webGLArray.get(), ec); break; - case f_uniformMatrix4fv: context->uniformMatrix4fv(location, transpose, webGLArray.get(), ec); break; + switch (f) { + case f_uniformMatrix2fv: + context->uniformMatrix2fv(location, transpose, webGLArray.get(), ec); + break; + case f_uniformMatrix3fv: + context->uniformMatrix3fv(location, transpose, webGLArray.get(), ec); + break; + case f_uniformMatrix4fv: + context->uniformMatrix4fv(location, transpose, webGLArray.get(), ec); + break; } - if (ec != 0) - setDOMException(exec, ec); + + setDOMException(exec, ec); return jsUndefined(); } - - float* array; - int size; - toArray<float>(exec, args.at(2), array, size); - - if (!array) + + Vector<float, 64> array; + if (!toVector(exec, args.at(2), array)) return throwError(exec, TypeError); - switch(f) { - case f_uniformMatrix2fv: context->uniformMatrix2fv(location, transpose, array, size, ec); break; - case f_uniformMatrix3fv: context->uniformMatrix3fv(location, transpose, array, size, ec); break; - case f_uniformMatrix4fv: context->uniformMatrix4fv(location, transpose, array, size, ec); break; + switch (f) { + case f_uniformMatrix2fv: + context->uniformMatrix2fv(location, transpose, array.data(), array.size(), ec); + break; + case f_uniformMatrix3fv: + context->uniformMatrix3fv(location, transpose, array.data(), array.size(), ec); + break; + case f_uniformMatrix4fv: + context->uniformMatrix4fv(location, transpose, array.data(), array.size(), ec); + break; } - if (ec != 0) - setDOMException(exec, ec); + + setDOMException(exec, ec); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSWebGLShortArrayCustom.cpp b/WebCore/bindings/js/JSWebGLShortArrayCustom.cpp index 462b09a..899b0c9 100644 --- a/WebCore/bindings/js/JSWebGLShortArrayCustom.cpp +++ b/WebCore/bindings/js/JSWebGLShortArrayCustom.cpp @@ -54,7 +54,7 @@ JSC::JSValue JSWebGLShortArray::set(JSC::ExecState* exec, JSC::ArgList const& ar if (args.size() == 2 && args.at(0).isInt32()) { // void set(in unsigned long index, in long value); unsigned index = args.at(0).toUInt32(exec); - impl()->set(index, static_cast<signed char>(args.at(1).toInt32(exec))); + impl()->set(index, static_cast<signed short>(args.at(1).toInt32(exec))); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSWebGLUnsignedByteArrayCustom.cpp b/WebCore/bindings/js/JSWebGLUnsignedByteArrayCustom.cpp index 35a545d..b576374 100644 --- a/WebCore/bindings/js/JSWebGLUnsignedByteArrayCustom.cpp +++ b/WebCore/bindings/js/JSWebGLUnsignedByteArrayCustom.cpp @@ -54,7 +54,7 @@ JSC::JSValue JSWebGLUnsignedByteArray::set(JSC::ExecState* exec, JSC::ArgList co if (args.size() == 2 && args.at(0).isInt32()) { // void set(in unsigned long index, in long value); unsigned index = args.at(0).toUInt32(exec); - impl()->set(index, static_cast<signed char>(args.at(1).toInt32(exec))); + impl()->set(index, static_cast<unsigned char>(args.at(1).toInt32(exec))); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSWebGLUnsignedIntArrayCustom.cpp b/WebCore/bindings/js/JSWebGLUnsignedIntArrayCustom.cpp index ea28111..c8b7454 100644 --- a/WebCore/bindings/js/JSWebGLUnsignedIntArrayCustom.cpp +++ b/WebCore/bindings/js/JSWebGLUnsignedIntArrayCustom.cpp @@ -38,7 +38,7 @@ namespace WebCore { void JSWebGLUnsignedIntArray::indexSetter(JSC::ExecState* exec, unsigned index, JSC::JSValue value) { - impl()->set(index, static_cast<unsigned int>(value.toInt32(exec))); + impl()->set(index, static_cast<unsigned int>(value.toUInt32(exec))); } JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, WebGLUnsignedIntArray* object) @@ -54,7 +54,7 @@ JSC::JSValue JSWebGLUnsignedIntArray::set(JSC::ExecState* exec, JSC::ArgList con if (args.size() == 2 && args.at(0).isInt32()) { // void set(in unsigned long index, in long value); unsigned index = args.at(0).toUInt32(exec); - impl()->set(index, static_cast<signed char>(args.at(1).toInt32(exec))); + impl()->set(index, static_cast<unsigned int>(args.at(1).toUInt32(exec))); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSWebGLUnsignedShortArrayCustom.cpp b/WebCore/bindings/js/JSWebGLUnsignedShortArrayCustom.cpp index 898cc06..0c82c3e 100644 --- a/WebCore/bindings/js/JSWebGLUnsignedShortArrayCustom.cpp +++ b/WebCore/bindings/js/JSWebGLUnsignedShortArrayCustom.cpp @@ -54,7 +54,7 @@ JSC::JSValue JSWebGLUnsignedShortArray::set(JSC::ExecState* exec, JSC::ArgList c if (args.size() == 2 && args.at(0).isInt32()) { // void set(in unsigned long index, in long value); unsigned index = args.at(0).toUInt32(exec); - impl()->set(index, static_cast<signed char>(args.at(1).toInt32(exec))); + impl()->set(index, static_cast<unsigned short>(args.at(1).toInt32(exec))); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSWebSocketConstructor.h b/WebCore/bindings/js/JSWebSocketConstructor.h index 069647a..633e612 100644 --- a/WebCore/bindings/js/JSWebSocketConstructor.h +++ b/WebCore/bindings/js/JSWebSocketConstructor.h @@ -31,6 +31,8 @@ #ifndef JSWebSocketConstructor_h #define JSWebSocketConstructor_h +#if ENABLE(WEB_SOCKETS) + #include "JSDOMBinding.h" namespace WebCore { @@ -45,6 +47,8 @@ class JSWebSocketConstructor : public DOMConstructorObject { virtual const JSC::ClassInfo* classInfo() const { return &s_info; } }; -} // namespace WebCore +} // namespace WebCore + +#endif // ENABLE(WEB_SOCKETS) -#endif // JSWebSocketConstructor_h +#endif // JSWebSocketConstructor_h diff --git a/WebCore/bindings/js/JSWorkerContextBase.cpp b/WebCore/bindings/js/JSWorkerContextBase.cpp index f0c4efa..2491f4d 100644 --- a/WebCore/bindings/js/JSWorkerContextBase.cpp +++ b/WebCore/bindings/js/JSWorkerContextBase.cpp @@ -42,7 +42,7 @@ namespace WebCore { ASSERT_CLASS_FITS_IN_CELL(JSWorkerContextBase); -const ClassInfo JSWorkerContextBase::s_info = { "WorkerContext", 0, 0, 0 }; +const ClassInfo JSWorkerContextBase::s_info = { "WorkerContext", &JSDOMGlobalObject::s_info, 0, 0 }; JSWorkerContextBase::JSWorkerContextBase(NonNullPassRefPtr<JSC::Structure> structure, PassRefPtr<WorkerContext> impl) : JSDOMGlobalObject(structure, new JSDOMGlobalObjectData(normalWorld(*impl->script()->globalData())), this) diff --git a/WebCore/bindings/js/JSWorkerContextCustom.cpp b/WebCore/bindings/js/JSWorkerContextCustom.cpp index 490d9b1..ab28674 100644 --- a/WebCore/bindings/js/JSWorkerContextCustom.cpp +++ b/WebCore/bindings/js/JSWorkerContextCustom.cpp @@ -32,8 +32,10 @@ #include "JSDOMBinding.h" #include "JSDOMGlobalObject.h" #include "JSEventListener.h" +#include "JSEventSourceConstructor.h" #include "JSMessageChannelConstructor.h" #include "JSMessagePort.h" +#include "JSWebSocketConstructor.h" #include "JSWorkerLocation.h" #include "JSWorkerNavigator.h" #include "JSXMLHttpRequestConstructor.h" @@ -43,10 +45,6 @@ #include "WorkerNavigator.h" #include <interpreter/Interpreter.h> -#if ENABLE(EVENTSOURCE) -#include "JSEventSourceConstructor.h" -#endif - using namespace JSC; namespace WebCore { @@ -93,6 +91,13 @@ JSValue JSWorkerContext::xmlHttpRequest(ExecState* exec) const return getDOMConstructor<JSXMLHttpRequestConstructor>(exec, this); } +#if ENABLE(WEB_SOCKETS) +JSValue JSWorkerContext::webSocket(ExecState* exec) const +{ + return getDOMConstructor<JSWebSocketConstructor>(exec, this); +} +#endif + JSValue JSWorkerContext::importScripts(ExecState* exec, const ArgList& args) { if (!args.size()) diff --git a/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp b/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp index 7ee2720..d35d53a 100644 --- a/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp +++ b/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp @@ -29,18 +29,18 @@ #include "config.h" #include "JSXMLHttpRequest.h" +#include "Blob.h" #include "DOMWindow.h" #include "Document.h" #include "Event.h" -#include "File.h" #include "Frame.h" #include "FrameLoader.h" #include "HTMLDocument.h" +#include "JSBlob.h" #include "JSDOMWindowCustom.h" #include "JSDocument.h" #include "JSEvent.h" #include "JSEventListener.h" -#include "JSFile.h" #include "XMLHttpRequest.h" #include <runtime/Error.h> #include <interpreter/Interpreter.h> @@ -109,8 +109,8 @@ JSValue JSXMLHttpRequest::send(ExecState* exec, const ArgList& args) impl()->send(ec); else if (val.inherits(&JSDocument::s_info)) impl()->send(toDocument(val), ec); - else if (val.inherits(&JSFile::s_info)) - impl()->send(toFile(val), ec); + else if (val.inherits(&JSBlob::s_info)) + impl()->send(toBlob(val), ec); else impl()->send(val.toString(exec), ec); } diff --git a/WebCore/bindings/js/ScheduledAction.cpp b/WebCore/bindings/js/ScheduledAction.cpp index 3223e53..be90125 100644 --- a/WebCore/bindings/js/ScheduledAction.cpp +++ b/WebCore/bindings/js/ScheduledAction.cpp @@ -117,7 +117,7 @@ void ScheduledAction::execute(Document* document) return; RefPtr<Frame> frame = window->impl()->frame(); - if (!frame || !frame->script()->isEnabled()) + if (!frame || !frame->script()->canExecuteScripts()) return; frame->script()->setProcessingTimerCallback(true); diff --git a/WebCore/bindings/js/ScheduledAction.h b/WebCore/bindings/js/ScheduledAction.h index 4ea727d..dd13ab1 100644 --- a/WebCore/bindings/js/ScheduledAction.h +++ b/WebCore/bindings/js/ScheduledAction.h @@ -40,7 +40,7 @@ namespace WebCore { * time interval, either once or repeatedly. Used for window.setTimeout() * and window.setInterval() */ - class ScheduledAction { + class ScheduledAction : public Noncopyable { public: static ScheduledAction* create(JSC::ExecState*, const JSC::ArgList&, DOMWrapperWorld* isolatedWorld); diff --git a/WebCore/bindings/js/ScriptCachedFrameData.cpp b/WebCore/bindings/js/ScriptCachedFrameData.cpp index f2b64de..16f18d3 100644 --- a/WebCore/bindings/js/ScriptCachedFrameData.cpp +++ b/WebCore/bindings/js/ScriptCachedFrameData.cpp @@ -73,8 +73,6 @@ ScriptCachedFrameData::~ScriptCachedFrameData() void ScriptCachedFrameData::restore(Frame* frame) { - Page* page = frame->page(); - JSLock lock(SilenceAssertionsOnly); ScriptController* scriptController = frame->script(); @@ -89,8 +87,9 @@ void ScriptCachedFrameData::restore(Frame* frame) windowShell->setWindow(window); else { windowShell->setWindow(frame->domWindow()); - if (world == debuggerWorld()) { - scriptController->attachDebugger(page->debugger()); + + if (Page* page = frame->page()) { + scriptController->attachDebugger(windowShell, page->debugger()); windowShell->window()->setProfileGroup(page->group().identifier()); } } diff --git a/WebCore/bindings/js/ScriptCachedFrameData.h b/WebCore/bindings/js/ScriptCachedFrameData.h index 5bcaed7..15c23c5 100644 --- a/WebCore/bindings/js/ScriptCachedFrameData.h +++ b/WebCore/bindings/js/ScriptCachedFrameData.h @@ -40,7 +40,7 @@ namespace WebCore { class DOMWindow; class DOMWrapperWorld; - class ScriptCachedFrameData { + class ScriptCachedFrameData : public Noncopyable { typedef HashMap< RefPtr<DOMWrapperWorld>, JSC::ProtectedPtr<JSDOMWindow> > JSDOMWindowSet; public: diff --git a/WebCore/bindings/js/ScriptCallStack.h b/WebCore/bindings/js/ScriptCallStack.h index 1907564..52362ea 100644 --- a/WebCore/bindings/js/ScriptCallStack.h +++ b/WebCore/bindings/js/ScriptCallStack.h @@ -49,6 +49,7 @@ namespace WebCore { ~ScriptCallStack(); ScriptState* state() const { return m_exec; } + ScriptState* globalState() const { return m_exec->lexicalGlobalObject()->globalExec(); } // frame retrieval methods const ScriptCallFrame &at(unsigned); unsigned size(); diff --git a/WebCore/bindings/js/ScriptController.cpp b/WebCore/bindings/js/ScriptController.cpp index 8d34f88..083e931 100644 --- a/WebCore/bindings/js/ScriptController.cpp +++ b/WebCore/bindings/js/ScriptController.cpp @@ -102,7 +102,7 @@ ScriptValue ScriptController::evaluateInWorld(const ScriptSourceCode& sourceCode } // evaluate code. Returns the JS return value or 0 - // if there was none, an error occured or the type couldn't be converted. + // if there was none, an error occurred or the type couldn't be converted. // inlineCode is true for <a href="javascript:doSomething()"> // and false for <script>doSomething()</script>. Check if it has the @@ -156,7 +156,7 @@ ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode) class IsolatedWorld : public DOMWrapperWorld { public: IsolatedWorld(JSGlobalData* globalData) - : DOMWrapperWorld(globalData) + : DOMWrapperWorld(globalData, false) { JSGlobalData::ClientData* clientData = globalData->clientData; ASSERT(clientData); @@ -183,19 +183,17 @@ void ScriptController::clearWindowShell() JSLock lock(SilenceAssertionsOnly); - // Clear the debugger from the current window before setting the new window. - DOMWrapperWorld* debugWorld = debuggerWorld(); - attachDebugger(0); - for (ShellMap::iterator iter = m_windowShells.begin(); iter != m_windowShells.end(); ++iter) { - DOMWrapperWorld* world = iter->first.get(); JSDOMWindowShell* windowShell = iter->second; + + // Clear the debugger from the current window before setting the new window. + attachDebugger(windowShell, 0); + windowShell->window()->willRemoveFromWindowShell(); windowShell->setWindow(m_frame->domWindow()); if (Page* page = m_frame->page()) { - if (world == debugWorld) - attachDebugger(page->debugger()); + attachDebugger(windowShell, page->debugger()); windowShell->window()->setProfileGroup(page->group().identifier()); } } @@ -215,8 +213,7 @@ JSDOMWindowShell* ScriptController::initScript(DOMWrapperWorld* world) windowShell->window()->updateDocument(); if (Page* page = m_frame->page()) { - if (world == debuggerWorld()) - attachDebugger(page->debugger()); + attachDebugger(windowShell, page->debugger()); windowShell->window()->setProfileGroup(page->group().identifier()); } @@ -291,16 +288,14 @@ bool ScriptController::anyPageIsProcessingUserGesture() const return false; } -bool ScriptController::isEnabled() +void ScriptController::attachDebugger(JSC::Debugger* debugger) { - Settings* settings = m_frame->settings(); - return m_frame->loader()->client()->allowJavaScript(settings && settings->isJavaScriptEnabled() && !m_frame->loader()->isSandboxed(SandboxScripts)); + for (ShellMap::iterator iter = m_windowShells.begin(); iter != m_windowShells.end(); ++iter) + attachDebugger(iter->second, debugger); } -void ScriptController::attachDebugger(JSC::Debugger* debugger) +void ScriptController::attachDebugger(JSDOMWindowShell* shell, JSC::Debugger* debugger) { - // FIXME: Should be able to debug isolated worlds. - JSDOMWindowShell* shell = existingWindowShell(debuggerWorld()); if (!shell) return; @@ -328,7 +323,7 @@ void ScriptController::updateSecurityOrigin() Bindings::RootObject* ScriptController::bindingRootObject() { - if (!isEnabled()) + if (!canExecuteScripts()) return 0; if (!m_bindingRootObject) { @@ -355,7 +350,7 @@ PassRefPtr<Bindings::RootObject> ScriptController::createRootObject(void* native NPObject* ScriptController::windowScriptNPObject() { if (!m_windowScriptNPObject) { - if (isEnabled()) { + if (canExecuteScripts()) { // JavaScript is enabled, so there is a JavaScript window object. // Return an NPObject bound to the window object. JSC::JSLock lock(SilenceAssertionsOnly); @@ -388,7 +383,7 @@ NPObject* ScriptController::createScriptObjectForPluginElement(HTMLPlugInElement JSObject* ScriptController::jsObjectForPluginElement(HTMLPlugInElement* plugin) { // Can't create JSObjects when JavaScript is disabled - if (!isEnabled()) + if (!canExecuteScripts()) return 0; // Create a JSObject bound to this element @@ -455,7 +450,7 @@ ScriptValue ScriptController::executeScriptInWorld(DOMWrapperWorld* world, const { ScriptSourceCode sourceCode(script, forceUserGesture ? KURL() : m_frame->loader()->url()); - if (!isEnabled() || isPaused()) + if (!canExecuteScripts() || isPaused()) return ScriptValue(); bool wasInExecuteScript = m_inExecuteScript; diff --git a/WebCore/bindings/js/ScriptController.h b/WebCore/bindings/js/ScriptController.h index 8801622..f3e5adf 100644 --- a/WebCore/bindings/js/ScriptController.h +++ b/WebCore/bindings/js/ScriptController.h @@ -110,9 +110,11 @@ public: bool processingUserGesture() const; bool anyPageIsProcessingUserGesture() const; - bool isEnabled(); + bool canExecuteScripts(); - void attachDebugger(JSC::Debugger*); + // Debugger can be 0 to detach any existing Debugger. + void attachDebugger(JSC::Debugger*); // Attaches/detaches in all worlds/window shells. + void attachDebugger(JSDOMWindowShell*, JSC::Debugger*); void setPaused(bool b) { m_paused = b; } bool isPaused() const { return m_paused; } diff --git a/WebCore/bindings/js/ScriptControllerMac.mm b/WebCore/bindings/js/ScriptControllerMac.mm index 650cb78..208aae8 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 (!isEnabled()) + if (!canExecuteScripts()) return 0; if (!m_windowScriptObject) { diff --git a/WebCore/bindings/js/ScriptEventListener.cpp b/WebCore/bindings/js/ScriptEventListener.cpp index 8399c7a..4325dc3 100644 --- a/WebCore/bindings/js/ScriptEventListener.cpp +++ b/WebCore/bindings/js/ScriptEventListener.cpp @@ -52,6 +52,9 @@ static const String& eventParameterName(bool isSVGEvent) PassRefPtr<JSLazyEventListener> createAttributeEventListener(Node* node, Attribute* attr) { ASSERT(node); + ASSERT(attr); + if (attr->isNull()) + return 0; int lineNumber = 1; String sourceURL; @@ -59,7 +62,7 @@ PassRefPtr<JSLazyEventListener> createAttributeEventListener(Node* node, Attribu // 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->isEnabled()) + if (!scriptController->canExecuteScripts()) return 0; if (!scriptController->xssAuditor()->canCreateInlineEventListener(attr->localName().string(), attr->value())) { @@ -79,11 +82,15 @@ PassRefPtr<JSLazyEventListener> createAttributeEventListener(Frame* frame, Attri if (!frame) return 0; + ASSERT(attr); + if (attr->isNull()) + return 0; + int lineNumber = 1; String sourceURL; ScriptController* scriptController = frame->script(); - if (!scriptController->isEnabled()) + if (!scriptController->canExecuteScripts()) return 0; if (!scriptController->xssAuditor()->canCreateInlineEventListener(attr->localName().string(), attr->value())) { diff --git a/WebCore/bindings/js/ScriptFunctionCall.cpp b/WebCore/bindings/js/ScriptFunctionCall.cpp index e38acb9..a2284bc 100644 --- a/WebCore/bindings/js/ScriptFunctionCall.cpp +++ b/WebCore/bindings/js/ScriptFunctionCall.cpp @@ -79,7 +79,7 @@ void ScriptFunctionCall::appendArgument(const JSC::UString& argument) void ScriptFunctionCall::appendArgument(const char* argument) { JSLock lock(SilenceAssertionsOnly); - m_arguments.append(jsString(m_exec, argument)); + m_arguments.append(jsString(m_exec, UString(argument))); } void ScriptFunctionCall::appendArgument(JSC::JSValue argument) diff --git a/WebCore/bindings/js/ScriptObject.h b/WebCore/bindings/js/ScriptObject.h index fed7339..0c993e1 100644 --- a/WebCore/bindings/js/ScriptObject.h +++ b/WebCore/bindings/js/ScriptObject.h @@ -47,6 +47,7 @@ namespace WebCore { ScriptObject(ScriptState*, JSC::JSObject*); ScriptObject() {} JSC::JSObject* jsObject() const { return asObject(jsValue()); } + ScriptState* scriptState() const { return m_scriptState; } bool set(const String& name, const String&); bool set(const char* name, const ScriptObject&); diff --git a/WebCore/bindings/js/ScriptState.cpp b/WebCore/bindings/js/ScriptState.cpp index b9f78ef..b9f334a 100644 --- a/WebCore/bindings/js/ScriptState.cpp +++ b/WebCore/bindings/js/ScriptState.cpp @@ -38,6 +38,12 @@ namespace WebCore { +ScriptState* mainWorldScriptState(Frame* frame) +{ + JSDOMWindowShell* shell = frame->script()->windowShell(mainThreadNormalWorld()); + return shell->window()->globalExec(); +} + ScriptState* scriptStateFromNode(DOMWrapperWorld* world, Node* node) { if (!node) @@ -48,7 +54,7 @@ ScriptState* scriptStateFromNode(DOMWrapperWorld* world, Node* node) Frame* frame = document->frame(); if (!frame) return 0; - if (!frame->script()->isEnabled()) + if (!frame->script()->canExecuteScripts()) return 0; return frame->script()->globalObject(world)->globalExec(); } diff --git a/WebCore/bindings/js/ScriptState.h b/WebCore/bindings/js/ScriptState.h index 6257929..0c7c575 100644 --- a/WebCore/bindings/js/ScriptState.h +++ b/WebCore/bindings/js/ScriptState.h @@ -36,6 +36,7 @@ namespace WebCore { class DOMWrapperWorld; + class Frame; class Node; class Page; @@ -45,6 +46,8 @@ namespace WebCore { // For now, the separation is purely by convention. typedef JSC::ExecState ScriptState; + ScriptState* mainWorldScriptState(Frame*); + ScriptState* scriptStateFromNode(DOMWrapperWorld*, Node*); ScriptState* scriptStateFromPage(DOMWrapperWorld*, Page*); diff --git a/WebCore/bindings/js/ScriptString.h b/WebCore/bindings/js/ScriptString.h index 6dab9a0..a33d639 100644 --- a/WebCore/bindings/js/ScriptString.h +++ b/WebCore/bindings/js/ScriptString.h @@ -33,6 +33,7 @@ #include "PlatformString.h" #include <runtime/UString.h> +#include <runtime/StringBuilder.h> namespace WebCore { @@ -57,7 +58,10 @@ public: ScriptString& operator+=(const String& s) { - m_str += s; + JSC::StringBuilder buffer; + buffer.append(m_str); + buffer.append(s); + m_str = buffer.release(); return *this; } diff --git a/WebCore/bindings/js/ScriptValue.cpp b/WebCore/bindings/js/ScriptValue.cpp index 5444e0e..ac92e14 100644 --- a/WebCore/bindings/js/ScriptValue.cpp +++ b/WebCore/bindings/js/ScriptValue.cpp @@ -32,8 +32,6 @@ #include <JavaScriptCore/APICast.h> #include <JavaScriptCore/JSValueRef.h> -#include "JSInspectedObjectWrapper.h" - #include <runtime/JSLock.h> #include <runtime/Protect.h> #include <runtime/UString.h> @@ -42,14 +40,6 @@ using namespace JSC; namespace WebCore { -#if ENABLE(INSPECTOR) -ScriptValue ScriptValue::quarantineValue(ScriptState* scriptState, const ScriptValue& value) -{ - JSLock lock(SilenceAssertionsOnly); - return ScriptValue(JSInspectedObjectWrapper::wrap(scriptState, value.jsValue())); -} -#endif - bool ScriptValue::getString(ScriptState* scriptState, String& result) const { if (!m_value) diff --git a/WebCore/bindings/js/ScriptValue.h b/WebCore/bindings/js/ScriptValue.h index e11fa55..b1eaa21 100644 --- a/WebCore/bindings/js/ScriptValue.h +++ b/WebCore/bindings/js/ScriptValue.h @@ -41,8 +41,6 @@ class String; class ScriptValue { public: - static ScriptValue quarantineValue(ScriptState* scriptState, const ScriptValue& value); - ScriptValue(JSC::JSValue value = JSC::JSValue()) : m_value(value) {} virtual ~ScriptValue() {} diff --git a/WebCore/bindings/v8/custom/V8XMLSerializerConstructor.cpp b/WebCore/bindings/js/ScriptWrappable.h index dd1c3ad..d70cab7 100644 --- a/WebCore/bindings/v8/custom/V8XMLSerializerConstructor.cpp +++ b/WebCore/bindings/js/ScriptWrappable.h @@ -1,10 +1,10 @@ /* - * 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 * 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 @@ -28,18 +28,16 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" -#include "XMLSerializer.h" - -#include "V8Binding.h" -#include "V8Proxy.h" +#ifndef ScriptWrappable_h +#define ScriptWrappable_h namespace WebCore { -CALLBACK_FUNC_DECL(XMLSerializerConstructor) -{ - INC_STATS("DOM.XMLSerializer.Constructor"); - return V8Proxy::constructDOMObject<V8ClassIndex::XMLSERIALIZER, XMLSerializer>(args); -} +class ScriptWrappable { +public: + ScriptWrappable() { } +}; } // namespace WebCore + +#endif // ScriptWrappable_h diff --git a/WebCore/bindings/js/SerializedScriptValue.cpp b/WebCore/bindings/js/SerializedScriptValue.cpp index 7c4ad62..fd9cb59 100644 --- a/WebCore/bindings/js/SerializedScriptValue.cpp +++ b/WebCore/bindings/js/SerializedScriptValue.cpp @@ -28,12 +28,14 @@ #include "SerializedScriptValue.h" #include "File.h" +#include "FileList.h" #include "JSDOMGlobalObject.h" #include "JSFile.h" #include "JSFileList.h" #include <JavaScriptCore/APICast.h> #include <runtime/DateInstance.h> #include <runtime/ExceptionHelpers.h> +#include <runtime/JSLock.h> #include <runtime/PropertyNameArray.h> #include <wtf/HashTraits.h> #include <wtf/Vector.h> @@ -141,6 +143,28 @@ private: unsigned m_length; }; +class SerializedFileList : public SharedSerializedData { +public: + static PassRefPtr<SerializedFileList> create(const FileList* list) + { + return adoptRef(new SerializedFileList(list)); + } + + unsigned length() const { return m_files.size(); } + const String& item(unsigned idx) { return m_files[idx]; } + +private: + SerializedFileList(const FileList* list) + { + unsigned length = list->length(); + m_files.reserveCapacity(length); + for (unsigned i = 0; i < length; i++) + m_files.append(list->item(i)->path().crossThreadString()); + } + + Vector<String> m_files; +}; + SerializedScriptValueData::SerializedScriptValueData(RefPtr<SerializedObject> data) : m_type(ObjectType) , m_sharedData(data) @@ -153,6 +177,12 @@ SerializedScriptValueData::SerializedScriptValueData(RefPtr<SerializedArray> dat { } +SerializedScriptValueData::SerializedScriptValueData(const FileList* fileList) + : m_type(FileListType) + , m_sharedData(SerializedFileList::create(fileList)) +{ +} + SerializedScriptValueData::SerializedScriptValueData(const File* file) : m_type(FileType) , m_string(file->path().crossThreadString()) @@ -169,6 +199,11 @@ SerializedObject* SharedSerializedData::asObject() return static_cast<SerializedObject*>(this); } +SerializedFileList* SharedSerializedData::asFileList() +{ + return static_cast<SerializedFileList*>(this); +} + static const unsigned maximumFilterRecursion = 40000; enum WalkerState { StateUnknown, ArrayStartState, ArrayStartVisitMember, ArrayEndVisitMember, ObjectStartState, ObjectStartVisitMember, ObjectEndVisitMember }; @@ -496,6 +531,8 @@ struct SerializingTreeWalker : public BaseWalker { JSObject* obj = asObject(value); if (obj->inherits(&JSFile::s_info)) return SerializedScriptValueData(toFile(obj)); + if (obj->inherits(&JSFileList::s_info)) + return SerializedScriptValueData(toFileList(obj)); CallData unusedData; if (value.getCallData(unusedData) == CallTypeNone) @@ -575,8 +612,10 @@ struct DeserializingTreeWalker : public BaseWalker { typedef JSObject* OutputObject; typedef SerializedObject::PropertyNameList PropertyList; - DeserializingTreeWalker(ExecState* exec, bool mustCopy) + DeserializingTreeWalker(ExecState* exec, JSGlobalObject* globalObject, bool mustCopy) : BaseWalker(exec) + , m_globalObject(globalObject) + , m_isDOMGlobalObject(globalObject->inherits(&JSDOMGlobalObject::s_info)) , m_mustCopy(mustCopy) { } @@ -605,14 +644,14 @@ struct DeserializingTreeWalker : public BaseWalker { JSArray* createOutputArray(unsigned length) { - JSArray* array = constructEmptyArray(m_exec); + JSArray* array = constructEmptyArray(m_exec, m_globalObject); array->setLength(length); return array; } JSObject* createOutputObject() { - return constructEmptyObject(m_exec); + return constructEmptyObject(m_exec, m_globalObject); } uint32_t length(RefPtr<SerializedArray> array) @@ -655,13 +694,27 @@ struct DeserializingTreeWalker : public BaseWalker { case SerializedScriptValueData::NumberType: return jsNumber(m_exec, value.asDouble()); case SerializedScriptValueData::DateType: - return new (m_exec) DateInstance(m_exec, value.asDouble()); + return new (m_exec) DateInstance(m_exec, m_globalObject->dateStructure(), value.asDouble()); case SerializedScriptValueData::FileType: - return toJS(m_exec, static_cast<JSDOMGlobalObject*>(m_exec->lexicalGlobalObject()), File::create(value.asString().crossThreadString())); - default: + if (!m_isDOMGlobalObject) + return jsNull(); + return toJS(m_exec, static_cast<JSDOMGlobalObject*>(m_globalObject), File::create(value.asString().crossThreadString())); + case SerializedScriptValueData::FileListType: { + if (!m_isDOMGlobalObject) + return jsNull(); + RefPtr<FileList> result = FileList::create(); + SerializedFileList* serializedFileList = value.asFileList(); + unsigned length = serializedFileList->length(); + for (unsigned i = 0; i < length; i++) + result->append(File::create(serializedFileList->item(i))); + return toJS(m_exec, static_cast<JSDOMGlobalObject*>(m_globalObject), result.get()); + } + case SerializedScriptValueData::EmptyType: ASSERT_NOT_REACHED(); - return JSValue(); + return jsNull(); } + ASSERT_NOT_REACHED(); + return jsNull(); } void getPropertyNames(RefPtr<SerializedObject> object, Vector<SerializedObject::PropertyNameList, 16>& properties) @@ -699,12 +752,15 @@ struct DeserializingTreeWalker : public BaseWalker { } private: + void* operator new(size_t); + JSGlobalObject* m_globalObject; + bool m_isDOMGlobalObject; bool m_mustCopy; }; -JSValue SerializedScriptValueData::deserialize(ExecState* exec, bool mustCopy) const +JSValue SerializedScriptValueData::deserialize(ExecState* exec, JSGlobalObject* global, bool mustCopy) const { - DeserializingTreeWalker context(exec, mustCopy); + DeserializingTreeWalker context(exec, global, mustCopy); return walk<DeserializingTreeWalker>(context, *this); } @@ -808,11 +864,14 @@ struct TeardownTreeWalker { case SerializedScriptValueData::StringType: case SerializedScriptValueData::ImmediateType: case SerializedScriptValueData::NumberType: + case SerializedScriptValueData::DateType: + case SerializedScriptValueData::EmptyType: + case SerializedScriptValueData::FileType: + case SerializedScriptValueData::FileListType: return true; - default: - ASSERT_NOT_REACHED(); - return JSValue(); } + ASSERT_NOT_REACHED(); + return true; } void getPropertyNames(RefPtr<SerializedObject> object, Vector<SerializedObject::PropertyNameList, 16>& properties) @@ -860,6 +919,7 @@ SerializedScriptValue::~SerializedScriptValue() PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(JSContextRef originContext, JSValueRef apiValue, JSValueRef* exception) { + JSLock lock(SilenceAssertionsOnly); ExecState* exec = toJS(originContext); JSValue value = toJS(exec, apiValue); PassRefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::create(exec, value); @@ -875,8 +935,9 @@ PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(JSContextRef ori JSValueRef SerializedScriptValue::deserialize(JSContextRef destinationContext, JSValueRef* exception) { + JSLock lock(SilenceAssertionsOnly); ExecState* exec = toJS(destinationContext); - JSValue value = deserialize(exec); + JSValue value = deserialize(exec, exec->lexicalGlobalObject()); if (exec->hadException()) { if (exception) *exception = toRef(exec, exec->exception()); diff --git a/WebCore/bindings/js/SerializedScriptValue.h b/WebCore/bindings/js/SerializedScriptValue.h index 57a4a66..347d8f2 100644 --- a/WebCore/bindings/js/SerializedScriptValue.h +++ b/WebCore/bindings/js/SerializedScriptValue.h @@ -34,14 +34,17 @@ typedef const struct OpaqueJSValue* JSValueRef; namespace WebCore { class File; - class SerializedObject; + class FileList; class SerializedArray; + class SerializedFileList; + class SerializedObject; class SharedSerializedData : public RefCounted<SharedSerializedData> { public: virtual ~SharedSerializedData() { } SerializedArray* asArray(); SerializedObject* asObject(); + SerializedFileList* asFileList(); }; class SerializedScriptValue; @@ -56,12 +59,13 @@ namespace WebCore { ObjectType, ArrayType, StringType, - FileType + FileType, + FileListType }; SerializedType type() const { return m_type; } static SerializedScriptValueData serialize(JSC::ExecState*, JSC::JSValue); - JSC::JSValue deserialize(JSC::ExecState*, bool mustCopy) const; + JSC::JSValue deserialize(JSC::ExecState*, JSC::JSGlobalObject*, bool mustCopy) const; ~SerializedScriptValueData() { @@ -81,6 +85,7 @@ namespace WebCore { } explicit SerializedScriptValueData(const File*); + explicit SerializedScriptValueData(const FileList*); explicit SerializedScriptValueData(JSC::JSValue value) : m_type(ImmediateType) @@ -130,6 +135,13 @@ namespace WebCore { return m_sharedData->asArray(); } + SerializedFileList* asFileList() const + { + ASSERT(m_type == FileListType); + ASSERT(m_sharedData); + return m_sharedData->asFileList(); + } + operator bool() const { return m_type != EmptyType; } SerializedScriptValueData release() @@ -184,11 +196,11 @@ namespace WebCore { return m_value.asString(); } - JSC::JSValue deserialize(JSC::ExecState* exec) + JSC::JSValue deserialize(JSC::ExecState* exec, JSC::JSGlobalObject* globalObject) { if (!m_value) return JSC::jsNull(); - return m_value.deserialize(exec, m_mustCopy); + return m_value.deserialize(exec, globalObject, m_mustCopy); } JSValueRef deserialize(JSContextRef, JSValueRef* exception); diff --git a/WebCore/bindings/js/WorkerScriptController.cpp b/WebCore/bindings/js/WorkerScriptController.cpp index 5e27ef7..adcc089 100644 --- a/WebCore/bindings/js/WorkerScriptController.cpp +++ b/WebCore/bindings/js/WorkerScriptController.cpp @@ -58,9 +58,6 @@ WorkerScriptController::WorkerScriptController(WorkerContext* workerContext) WorkerScriptController::~WorkerScriptController() { m_workerContextWrapper = 0; // Unprotect the global object. - - ASSERT(!m_globalData->heap.protectedObjectCount()); - ASSERT(!m_globalData->heap.isBusy()); m_globalData->heap.destroy(); } diff --git a/WebCore/bindings/objc/DOMHTML.h b/WebCore/bindings/objc/DOMHTML.h index c336c04..882e397 100644 --- a/WebCore/bindings/objc/DOMHTML.h +++ b/WebCore/bindings/objc/DOMHTML.h @@ -26,6 +26,7 @@ #import <WebCore/DOMCore.h> +#import <WebCore/DOMBlob.h> #import <WebCore/DOMFile.h> #import <WebCore/DOMFileList.h> #import <WebCore/DOMHTMLAnchorElement.h> diff --git a/WebCore/bindings/objc/DOMInternal.h b/WebCore/bindings/objc/DOMInternal.h index 72f63d2..6d2442b 100644 --- a/WebCore/bindings/objc/DOMInternal.h +++ b/WebCore/bindings/objc/DOMInternal.h @@ -87,3 +87,13 @@ WebCore::NodeFilter* core(DOMNodeFilter *); DOMNativeXPathNSResolver *kit(WebCore::XPathNSResolver*); WebCore::XPathNSResolver* core(DOMNativeXPathNSResolver *); #endif // ENABLE(XPATH) + +inline NSTimeInterval kit(double msSinceEpoch) +{ + return msSinceEpoch / 1000.0 - NSTimeIntervalSince1970; +} + +inline double core(NSTimeInterval sec) +{ + return sec * 1000.0 + NSTimeIntervalSince1970; +} diff --git a/WebCore/bindings/objc/PublicDOMInterfaces.h b/WebCore/bindings/objc/PublicDOMInterfaces.h index 9221037..ea46436 100644 --- a/WebCore/bindings/objc/PublicDOMInterfaces.h +++ b/WebCore/bindings/objc/PublicDOMInterfaces.h @@ -235,7 +235,14 @@ @interface DOMEntityReference : DOMNode WEBKIT_VERSION_1_3 @end -@interface DOMFile : DOMObject WEBKIT_VERSION_4_0 +@interface DOMBlob : DOMObject WEBKIT_VERSION_4_0 +@property(readonly) unsigned long long size; +@end + +@interface DOMFile : DOMBlob WEBKIT_VERSION_4_0 +@property(readonly, copy) NSString *name; + +// FIXME: obsolete properties. To be removed. @property(readonly, copy) NSString *fileName; @property(readonly) unsigned long long fileSize; @end diff --git a/WebCore/bindings/scripts/CodeGenerator.pm b/WebCore/bindings/scripts/CodeGenerator.pm index c1cb0a0..dc3c7c0 100644 --- a/WebCore/bindings/scripts/CodeGenerator.pm +++ b/WebCore/bindings/scripts/CodeGenerator.pm @@ -43,10 +43,11 @@ my %primitiveTypeHash = ("int" => 1, "short" => 1, "long" => 1, "long long" => 1 "unsigned int" => 1, "unsigned short" => 1, "unsigned long" => 1, "unsigned long long" => 1, "float" => 1, "double" => 1, - "boolean" => 1, "void" => 1); + "boolean" => 1, "void" => 1, + "Date" => 1); my %podTypeHash = ("SVGNumber" => 1, "SVGTransform" => 1); -my %podTypesWithWritablePropertiesHash = ("SVGLength" => 1, "SVGMatrix" => 1, "SVGPoint" => 1, "SVGRect" => 1); +my %podTypesWithWritablePropertiesHash = ("SVGAngle" => 1, "SVGLength" => 1, "SVGMatrix" => 1, "SVGPoint" => 1, "SVGPreserveAspectRatio" => 1, "SVGRect" => 1); my %stringTypeHash = ("DOMString" => 1, "AtomicString" => 1); my %nonPointerTypeHash = ("DOMTimeStamp" => 1, "CompareHow" => 1, "SVGPaintType" => 1); diff --git a/WebCore/bindings/scripts/CodeGeneratorCOM.pm b/WebCore/bindings/scripts/CodeGeneratorCOM.pm deleted file mode 100644 index e98379b..0000000 --- a/WebCore/bindings/scripts/CodeGeneratorCOM.pm +++ /dev/null @@ -1,1319 +0,0 @@ -# -# Copyright (C) 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org> -# Copyright (C) 2006 Anders Carlsson <andersca@mac.com> -# Copyright (C) 2006, 2007 Samuel Weinig <sam@webkit.org> -# Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org> -# Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. -# -# 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 CodeGeneratorCOM; - -use File::stat; - -# Global Variables -my $module = ""; -my $outputDir = ""; - -my @IDLHeader = (); -my @IDLContent = (); -my %IDLIncludes = (); -my %IDLForwardDeclarations = (); -my %IDLDontForwardDeclare = (); -my %IDLImports = (); -my %IDLDontImport = (); - -my @CPPInterfaceHeader = (); - -my @CPPHeaderHeader = (); -my @CPPHeaderContent = (); -my %CPPHeaderIncludes = (); -my %CPPHeaderIncludesAngle = (); -my %CPPHeaderForwardDeclarations = (); -my %CPPHeaderDontForwardDeclarations = (); - -my @CPPImplementationHeader = (); -my @CPPImplementationContent = (); -my %CPPImplementationIncludes = (); -my %CPPImplementationWebCoreIncludes = (); -my %CPPImplementationIncludesAngle = (); -my %CPPImplementationDontIncludes = (); - -my @additionalInterfaceDefinitions = (); - -my $DASHES = "----------------------------------------"; -my $TEMP_PREFIX = "GEN_"; - -# Hashes - -my %includeCorrector = map {($_, 1)} qw{UIEvent KeyboardEvent MouseEvent - MutationEvent OverflowEvent WheelEvent}; - -my %conflictMethod = ( - # FIXME: Add C language keywords? -); - -# Default License Templates -my @licenseTemplate = split(/\r/, << "EOF"); -/* - * Copyright (C) 2007 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. - * 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. - */ -EOF - -# Default constructor -sub new -{ - my $object = shift; - my $reference = { }; - - $codeGenerator = shift; - $outputDir = shift; - - bless($reference, $object); - return $reference; -} - -sub finish -{ - my $object = shift; -} - -# Params: 'domClass' struct -sub GenerateInterface -{ - my $object = shift; - my $dataNode = shift; - my $defines = shift; - - my $name = $dataNode->name; - - my $pureInterface = $dataNode->extendedAttributes->{"PureInterface"}; - - # Start actual generation.. - $object->GenerateIDL($dataNode, $pureInterface); - if ($pureInterface) { - $object->GenerateInterfaceHeader($dataNode); - } else { - $object->GenerateCPPHeader($dataNode); - $object->GenerateCPPImplementation($dataNode); - } - - # Write changes. - $object->WriteData($name, $pureInterface); -} - -# Params: 'idlDocument' struct -sub GenerateModule -{ - my $object = shift; - my $dataNode = shift; - - $module = $dataNode->module; -} - -sub GetInterfaceName -{ - my $name = $codeGenerator->StripModule(shift); - - die "GetInterfaceName should only be used on interfaces." if ($codeGenerator->IsStringType($name) or $codeGenerator->IsPrimitiveType($name)); - - # special cases - return "I" . $TEMP_PREFIX . "DOMAbstractView" if $name eq "DOMWindow"; - return "I" . $TEMP_PREFIX . $name if $name eq "DOMImplementation" or $name eq "DOMTimeStamp"; - - # Default, assume COM type has the same type name as - # idl type prefixed with "IDOM". - return "I" . $TEMP_PREFIX . "DOM" . $name; -} - -sub GetClassName -{ - my $name = $codeGenerator->StripModule(shift); - - # special cases - return "BSTR" if $codeGenerator->IsStringType($name); - return "BOOL" if $name eq "boolean"; - return "unsigned" if $name eq "unsigned long"; - return "int" if $name eq "long"; - return $name if $codeGenerator->IsPrimitiveType($name); - return $TEMP_PREFIX . "DOMAbstractView" if $name eq "DOMWindow"; - return $TEMP_PREFIX . $name if $name eq "DOMImplementation" or $name eq "DOMTimeStamp"; - - # Default, assume COM type has the same type name as - # idl type prefixed with "DOM". - return $TEMP_PREFIX . "DOM" . $name; -} - -sub GetCOMType -{ - my ($type) = @_; - - die "Don't use GetCOMType for string types, use one of In/Out variants instead." if $codeGenerator->IsStringType($type); - - return "BOOL" if $type eq "boolean"; - return "UINT" if $type eq "unsigned long"; - return "INT" if $type eq "long"; - return $type if $codeGenerator->IsPrimitiveType($type) or $type eq "DOMTimeStamp"; - # return "unsigned short" if $type eq "CompareHow" or $type eq "SVGPaintType"; - - return GetInterfaceName($type) . "*"; -} - -sub GetCOMTypeIn -{ - my ($type) = @_; - return "LPCTSTR" if $codeGenerator->IsStringType($type); - return GetCOMType($type); -} - -sub GetCOMTypeOut -{ - my ($type) = @_; - return "BSTR" if $codeGenerator->IsStringType($type); - return GetCOMType($type); -} - -sub IDLTypeToImplementationType -{ - my $type = $codeGenerator->StripModule(shift); - - return "bool" if $type eq "boolean"; - return "unsigned" if $type eq "unsigned long"; - return "int" if $type eq "long"; - return $type if $codeGenerator->IsPrimitiveType($type); - - return "WebCore::String" if $codeGenerator->IsStringType($type); - return "WebCore::${type}"; -} - -sub StripNamespace -{ - my ($type) = @_; - - $type =~ s/^WebCore:://; - - return $type; -} - -sub GetParentInterface -{ - my ($dataNode) = @_; - return "I" . $TEMP_PREFIX . "DOMObject" if (@{$dataNode->parents} == 0); - return GetInterfaceName($codeGenerator->StripModule($dataNode->parents(0))); -} - -sub GetParentClass -{ - my ($dataNode) = @_; - return $TEMP_PREFIX . "DOMObject" if (@{$dataNode->parents} == 0); - return GetClassName($codeGenerator->StripModule($dataNode->parents(0))); -} - -sub AddForwardDeclarationsForTypeInIDL -{ - my $type = $codeGenerator->StripModule(shift); - - return if $codeGenerator->IsNonPointerType($type) or $codeGenerator->IsStringType($type); - - my $interface = GetInterfaceName($type); - $IDLForwardDeclarations{$interface} = 1; - $IDLImports{$interface} = 1; -} - -sub AddIncludesForTypeInCPPHeader -{ - my $type = $codeGenerator->StripModule(shift); - my $useAngleBrackets = shift; - - return if $codeGenerator->IsNonPointerType($type); - - # Add special Cases HERE - - if ($type =~ m/^I/) { - $type = "WebKit"; - } - - if ($useAngleBrackets) { - $CPPHeaderIncludesAngle{"$type.h"} = 1; - return; - } - - if ($type eq "GEN_DOMImplementation") { - $CPPHeaderIncludes{"GEN_DOMDOMImplementation.h"} = 1; - return; - } - - if ($type eq "IGEN_DOMImplementation") { - $CPPHeaderIncludes{"IGEN_DOMDOMImplementation.h"} = 1; - return; - } - - $CPPHeaderIncludes{"$type.h"} = 1; -} - -sub AddForwardDeclarationsForTypeInCPPHeader -{ - my $type = $codeGenerator->StripModule(shift); - - return if $codeGenerator->IsNonPointerType($type) or $codeGenerator->IsStringType($type); - - my $interface = GetInterfaceName($type); - $CPPHeaderForwardDeclarations{$interface} = 1; -} - -sub AddIncludesForTypeInCPPImplementation -{ - my $type = $codeGenerator->StripModule(shift); - - die "Include type not supported!" if $includeCorrector{$type}; - - return if $codeGenerator->IsNonPointerType($type); - - if ($codeGenerator->IsStringType($type)) { - $CPPImplementationWebCoreIncludes{"AtomicString.h"} = 1; - $CPPImplementationWebCoreIncludes{"BString.h"} = 1; - $CPPImplementationWebCoreIncludes{"KURL.h"} = 1; - return; - } - - # Special casing - $CPPImplementationWebCoreIncludes{"NameNodeList.h"} = 1 if $type eq "NodeList"; - $CPPImplementationWebCoreIncludes{"CSSMutableStyleDeclaration.h"} = 1 if $type eq "CSSStyleDeclaration"; - - # Add implementation type - $CPPImplementationWebCoreIncludes{StripNamespace(IDLTypeToImplementationType($type)) . ".h"} = 1; - - my $COMClassName = GetClassName($type); - $CPPImplementationIncludes{"${COMClassName}.h"} = 1; -} - -sub GetAdditionalInterfaces -{ - # This function does nothing, but it stays here for future multiple inheritance support. - my $type = $codeGenerator->StripModule(shift); - return (); -} - -sub GenerateIDL -{ - my ($object, $dataNode, $pureInterface) = @_; - - my $inInterfaceName = $dataNode->name; - my $outInterfaceName = GetInterfaceName($inInterfaceName); - my $uuid = $dataNode->extendedAttributes->{"InterfaceUUID"} || die "All classes require an InterfaceUUID extended attribute."; - - my $parentInterfaceName = ($pureInterface) ? "IUnknown" : GetParentInterface($dataNode); - - my $numConstants = @{$dataNode->constants}; - my $numAttributes = @{$dataNode->attributes}; - my $numFunctions = @{$dataNode->functions}; - - # - Add default header template - @IDLHeader = @licenseTemplate; - push(@IDLHeader, "\n"); - - # - INCLUDES - - push(@IDLHeader, "#ifndef DO_NO_IMPORTS\n"); - push(@IDLHeader, "import \"oaidl.idl\";\n"); - push(@IDLHeader, "import \"ocidl.idl\";\n"); - push(@IDLHeader, "#endif\n\n"); - - unless ($pureInterface) { - push(@IDLHeader, "#ifndef DO_NO_IMPORTS\n"); - push(@IDLHeader, "import \"${parentInterfaceName}.idl\";\n"); - push(@IDLHeader, "#endif\n\n"); - - $IDLDontForwardDeclare{$outInterfaceName} = 1; - $IDLDontImport{$outInterfaceName} = 1; - $IDLDontForwardDeclare{$parentInterfaceName} = 1; - $IDLDontImport{$parentInterfaceName} = 1; - } - - # - Begin - # -- Attributes - push(@IDLContent, "[\n"); - push(@IDLContent, " object,\n"); - push(@IDLContent, " oleautomation,\n"); - push(@IDLContent, " uuid(" . $uuid . "),\n"); - push(@IDLContent, " pointer_default(unique)\n"); - push(@IDLContent, "]\n"); - - # -- Interface - push(@IDLContent, "interface " . $outInterfaceName . " : " . $parentInterfaceName . "\n"); - push(@IDLContent, "{\n"); - - - # - FIXME: Add constants. - - - # - Add attribute getters/setters. - if ($numAttributes > 0) { - foreach my $attribute (@{$dataNode->attributes}) { - my $attributeName = $attribute->signature->name; - my $attributeIDLType = $attribute->signature->type; - my $attributeTypeIn = GetCOMTypeIn($attributeIDLType); - my $attributeTypeOut = GetCOMTypeOut($attributeIDLType); - my $attributeIsReadonly = ($attribute->type =~ /^readonly/); - - AddForwardDeclarationsForTypeInIDL($attributeIDLType); - - unless ($attributeIsReadonly) { - # Setter - my $setterName = "set" . $codeGenerator->WK_ucfirst($attributeName); - my $setter = " HRESULT " . $setterName . "([in] " . $attributeTypeIn . ");\n"; - push(@IDLContent, $setter); - } - - # Getter - my $getter = " HRESULT " . $attributeName . "([out, retval] " . $attributeTypeOut . "*);\n\n"; - push(@IDLContent, $getter); - } - } - - # - Add functions. - if ($numFunctions > 0) { - foreach my $function (@{$dataNode->functions}) { - my $functionName = $function->signature->name; - my $returnIDLType = $function->signature->type; - my $returnType = GetCOMTypeOut($returnIDLType); - my $noReturn = ($returnType eq "void"); - - AddForwardDeclarationsForTypeInIDL($returnIDLType); - - my @paramArgList = (); - foreach my $param (@{$function->parameters}) { - my $paramName = $param->name; - my $paramIDLType = $param->type; - my $paramType = GetCOMTypeIn($param->type); - - AddForwardDeclarationsForTypeInIDL($paramIDLType); - - # Form parameter - my $parameter = "[in] ${paramType} ${paramName}"; - - # Add parameter to function signature - push(@paramArgList, $parameter); - } - - unless ($noReturn) { - my $resultParameter = "[out, retval] " . $returnType . "* result"; - push(@paramArgList, $resultParameter); - } - - my $functionSig = " HRESULT " . $functionName . "("; - $functionSig .= join(", ", @paramArgList); - $functionSig .= ");\n\n"; - push(@IDLContent, $functionSig); - } - } - - # - End - push(@IDLContent, "}\n\n"); -} - -sub GenerateInterfaceHeader -{ - my ($object, $dataNode) = @_; - - my $IDLType = $dataNode->name; - my $implementationClass = IDLTypeToImplementationType($IDLType); - my $implementationClassWithoutNamespace = StripNamespace($implementationClass); - my $className = GetClassName($IDLType); - my $interfaceName = GetInterfaceName($IDLType); - - # - Add default header template - @CPPInterfaceHeader = @licenseTemplate; - push(@CPPInterfaceHeader, "\n"); - - # - Header guards - - push(@CPPInterfaceHeader, "#ifndef " . $className . "_h\n"); - push(@CPPInterfaceHeader, "#define " . $className . "_h\n\n"); - - # - Forward Declarations - - push(@CPPInterfaceHeader, "interface ${interfaceName};\n\n"); - push(@CPPInterfaceHeader, "namespace WebCore {\n"); - push(@CPPInterfaceHeader, " class ${implementationClassWithoutNamespace};\n"); - push(@CPPInterfaceHeader, "}\n\n"); - - # - Default Interface Creator - - push(@CPPInterfaceHeader, "${interfaceName}* to${interfaceName}(${implementationClass}*) { return 0; }\n\n"); - - push(@CPPInterfaceHeader, "#endif // " . $className . "_h\n"); -} - -# ----------------------------------------------------------------------------- -# CPP Helper Functions -# ----------------------------------------------------------------------------- - -sub GenerateCPPAttributeSignature -{ - my ($attribute, $className, $options) = @_; - - my $attributeName = $attribute->signature->name; - my $isReadonly = ($attribute->type =~ /^readonly/); - - my $newline = $$options{"NewLines"} ? "\n" : ""; - my $indent = $$options{"Indent"} ? " " x $$options{"Indent"} : ""; - my $semicolon = $$options{"IncludeSemiColon"} ? ";" : ""; - my $virtual = $$options{"AddVirtualKeyword"} ? "virtual " : ""; - my $class = $$options{"UseClassName"} ? "${className}::" : ""; - my $forwarder = $$options{"Forwarder"} ? 1 : 0; - my $joiner = ($$options{"NewLines"} ? "\n" . $indent . " " : ""); - - my %attributeSignatures = (); - - unless ($isReadonly) { - my $attributeTypeIn = GetCOMTypeIn($attribute->signature->type); - my $setterName = "set" . $codeGenerator->WK_ucfirst($attributeName); - my $setter = $indent . $virtual . "HRESULT STDMETHODCALLTYPE ". $class . $setterName . "("; - $setter .= $joiner . "/* [in] */ ${attributeTypeIn} ${attributeName})" . $semicolon . $newline; - if ($forwarder) { - $setter .= " { return " . $$options{"Forwarder"} . "::" . $setterName . "(${attributeName}); }\n"; - } - $attributeSignatures{"Setter"} = $setter; - } - - my $attributeTypeOut = GetCOMTypeOut($attribute->signature->type); - my $getter = $indent . $virtual . "HRESULT STDMETHODCALLTYPE " . $class . $attributeName . "("; - $getter .= $joiner . "/* [retval][out] */ ${attributeTypeOut}* result)" . $semicolon . $newline; - if ($forwarder) { - $getter .= " { return " . $$options{"Forwarder"} . "::" . $attributeName . "(result); }\n"; - } - $attributeSignatures{"Getter"} = $getter; - - return %attributeSignatures; -} - - -sub GenerateCPPAttribute -{ - my ($attribute, $className, $implementationClass, $IDLType) = @_; - - my $implementationClassWithoutNamespace = StripNamespace($implementationClass); - - my $attributeName = $attribute->signature->name; - my $attributeIDLType = $attribute->signature->type; - my $hasSetterException = @{$attribute->setterExceptions}; - my $hasGetterException = @{$attribute->getterExceptions}; - my $isReadonly = ($attribute->type =~ /^readonly/); - my $attributeTypeIsPrimitive = $codeGenerator->IsPrimitiveType($attributeIDLType); - my $attributeTypeIsString = $codeGenerator->IsStringType($attributeIDLType); - my $attributeImplementationType = IDLTypeToImplementationType($attributeIDLType); - my $attributeImplementationTypeWithoutNamespace = StripNamespace($attributeImplementationType); - my $attributeTypeCOMClassName = GetClassName($attributeIDLType); - - $CPPImplementationWebCoreIncludes{"ExceptionCode.h"} = 1 if $hasSetterException or $hasGetterException; - - my %signatures = GenerateCPPAttributeSignature($attribute, $className, { "NewLines" => 1, - "Indent" => 0, - "IncludeSemiColon" => 0, - "UseClassName" => 1, - "AddVirtualKeyword" => 0 }); - - my %attrbutesToReturn = (); - - unless ($isReadonly) { - my @setterImplementation = (); - push(@setterImplementation, $signatures{"Setter"}); - push(@setterImplementation, "{\n"); - - my $setterName = "set" . $codeGenerator->WK_ucfirst($attributeName); - - my @setterParams = (); - if ($attributeTypeIsString) { - push(@setterParams, $attributeName); - if ($hasSetterException) { - push(@setterImplementation, " WebCore::ExceptionCode ec = 0;\n"); - push(@setterParams, "ec"); - } - } elsif ($attributeTypeIsPrimitive) { - if ($attribute->signature->extendedAttributes->{"ConvertFromString"}) { - push(@setterParams, "WebCore::String::number(${attributeName})"); - } elsif ($attributeIDLType eq "boolean") { - push(@setterParams, "!!${attributeName}"); - } else { - my $primitiveImplementationType = IDLTypeToImplementationType($attributeIDLType); - push(@setterParams, "static_cast<${primitiveImplementationType}>(${attributeName})"); - } - - if ($hasSetterException) { - push(@setterImplementation, " WebCore::ExceptionCode ec = 0;\n"); - push(@setterParams, "ec"); - } - } else { - $CPPImplementationWebCoreIncludes{"COMPtr.h"} = 1; - - push(@setterImplementation, " if (!${attributeName})\n"); - push(@setterImplementation, " return E_POINTER;\n\n"); - push(@setterImplementation, " COMPtr<${attributeTypeCOMClassName}> ptr(Query, ${attributeName});\n"); - push(@setterImplementation, " if (!ptr)\n"); - push(@setterImplementation, " return E_NOINTERFACE;\n"); - - push(@setterParams, "ptr->impl${attributeImplementationTypeWithoutNamespace}()"); - if ($hasSetterException) { - push(@setterImplementation, " WebCore::ExceptionCode ec = 0;\n"); - push(@setterParams, "ec"); - } - } - - # FIXME: CHECK EXCEPTION AND DO SOMETHING WITH IT - - my $reflect = $attribute->signature->extendedAttributes->{"Reflect"}; - my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"}; - if ($reflect || $reflectURL) { - my $contentAttributeName = (($reflect || $reflectURL) eq "1") ? $attributeName : ($reflect || $reflectURL); - my $namespace = $codeGenerator->NamespaceForAttributeName($IDLType, $contentAttributeName); - $CPPImplementationWebCoreIncludes{"${namespace}.h"} = 1; - push(@setterImplementation, " impl${implementationClassWithoutNamespace}()->setAttribute(WebCore::${namespace}::${contentAttributeName}Attr, " . join(", ", @setterParams) . ");\n"); - } else { - push(@setterImplementation, " impl${implementationClassWithoutNamespace}()->${setterName}(" . join(", ", @setterParams) . ");\n"); - } - push(@setterImplementation, " return S_OK;\n"); - push(@setterImplementation, "}\n\n"); - - $attrbutesToReturn{"Setter"} = join("", @setterImplementation); - } - - my @getterImplementation = (); - push(@getterImplementation, $signatures{"Getter"}); - push(@getterImplementation, "{\n"); - push(@getterImplementation, " if (!result)\n"); - push(@getterImplementation, " return E_POINTER;\n\n"); - - my $implementationGetter; - my $reflect = $attribute->signature->extendedAttributes->{"Reflect"}; - my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"}; - if ($reflect || $reflectURL) { - my $contentAttributeName = (($reflect || $reflectURL) eq "1") ? $attributeName : ($reflect || $reflectURL); - my $namespace = $codeGenerator->NamespaceForAttributeName($IDLType, $contentAttributeName); - $implIncludes{"${namespace}.h"} = 1; - my $getAttributeFunctionName = $reflectURL ? "getURLAttribute" : "getAttribute"; - $implementationGetter = "impl${implementationClassWithoutNamespace}()->${getAttributeFunctionName}(WebCore::${namespace}::${contentAttributeName}Attr)"; - } else { - $implementationGetter = "impl${implementationClassWithoutNamespace}()->" . $codeGenerator->WK_lcfirst($attributeName) . "(" . ($hasGetterException ? "ec" : ""). ")"; - } - - push(@getterImplementation, " WebCore::ExceptionCode ec = 0;\n") if $hasGetterException; - - if ($attributeTypeIsString) { - push(@getterImplementation, " *result = WebCore::BString(${implementationGetter}).release();\n"); - } elsif ($attributeTypeIsPrimitive) { - if ($attribute->signature->extendedAttributes->{"ConvertFromString"}) { - push(@getterImplementation, " *result = static_cast<${attributeTypeCOMClassName}>(${implementationGetter}.toInt());\n"); - } else { - push(@getterImplementation, " *result = static_cast<${attributeTypeCOMClassName}>(${implementationGetter});\n"); - } - } else { - $CPPImplementationIncludesAngle{"wtf/GetPtr.h"} = 1; - my $attributeTypeCOMInterfaceName = GetInterfaceName($attributeIDLType); - push(@getterImplementation, " *result = 0;\n"); - push(@getterImplementation, " ${attributeImplementationType}* resultImpl = WTF::getPtr(${implementationGetter});\n"); - push(@getterImplementation, " if (!resultImpl)\n"); - push(@getterImplementation, " return E_POINTER;\n\n"); - push(@getterImplementation, " *result = to${attributeTypeCOMInterfaceName}(resultImpl);\n"); - } - - # FIXME: CHECK EXCEPTION AND DO SOMETHING WITH IT - - push(@getterImplementation, " return S_OK;\n"); - push(@getterImplementation, "}\n\n"); - - $attrbutesToReturn{"Getter"} = join("", @getterImplementation); - - return %attrbutesToReturn; -} - -sub GenerateCPPFunctionSignature -{ - my ($function, $className, $options) = @_; - - my $functionName = $function->signature->name; - my $returnIDLType = $function->signature->type; - my $returnType = GetCOMTypeOut($returnIDLType); - my $noReturn = ($returnType eq "void"); - - my $newline = $$options{"NewLines"} ? "\n" : ""; - my $indent = $$options{"Indent"} ? " " x $$options{"Indent"} : ""; - my $semicolon = $$options{"IncludeSemiColon"} ? ";" : ""; - my $virtual = $$options{"AddVirtualKeyword"} ? "virtual " : ""; - my $class = $$options{"UseClassName"} ? "${className}::" : ""; - my $forwarder = $$options{"Forwarder"} ? 1 : 0; - my $joiner = ($$options{"NewLines"} ? "\n" . $indent . " " : " "); - - my @paramArgList = (); - foreach my $param (@{$function->parameters}) { - my $paramName = $param->name; - my $paramType = GetCOMTypeIn($param->type); - my $parameter = "/* [in] */ ${paramType} ${paramName}"; - push(@paramArgList, $parameter); - } - - unless ($noReturn) { - my $resultParameter .= "/* [out, retval] */ ${returnType}* result"; - push(@paramArgList, $resultParameter); - } - - my $functionSig = $indent . $virtual . "HRESULT STDMETHODCALLTYPE " . $class . $functionName . "("; - $functionSig .= $joiner . join("," . $joiner, @paramArgList) if @paramArgList > 0; - $functionSig .= ")" . $semicolon . $newline; - if ($forwarder) { - my @paramNameList = (); - push(@paramNameList, $_->name) foreach (@{$function->parameters}); - push(@paramNameList, "result") unless $noReturn; - $functionSig .= " { return " . $$options{"Forwarder"} . "::" . $functionName . "(" . join(", ", @paramNameList) . "); }\n"; - } - - return $functionSig -} - -sub GenerateCPPFunction -{ - my ($function, $className, $implementationClass) = @_; - - my @functionImplementation = (); - - my $signature = GenerateCPPFunctionSignature($function, $className, { "NewLines" => 1, - "Indent" => 0, - "IncludeSemiColon" => 0, - "UseClassName" => 1, - "AddVirtualKeyword" => 0 }); - - my $implementationClassWithoutNamespace = StripNamespace($implementationClass); - - my $functionName = $function->signature->name; - my $returnIDLType = $function->signature->type; - my $noReturn = ($returnIDLType eq "void"); - my $raisesExceptions = @{$function->raisesExceptions}; - - AddIncludesForTypeInCPPImplementation($returnIDLType); - $CPPImplementationWebCoreIncludes{"ExceptionCode.h"} = 1 if $raisesExceptions; - - my %needsCustom = (); - my @parameterInitialization = (); - my @parameterList = (); - foreach my $param (@{$function->parameters}) { - my $paramName = $param->name; - my $paramIDLType = $param->type; - - my $paramTypeIsPrimitive = $codeGenerator->IsPrimitiveType($paramIDLType); - my $paramTypeIsString = $codeGenerator->IsStringType($paramIDLType); - - $needsCustom{"NodeToReturn"} = $paramName if $param->extendedAttributes->{"Return"}; - - AddIncludesForTypeInCPPImplementation($paramIDLType); - - # FIXME: We may need to null check the arguments as well - - if ($paramTypeIsString) { - push(@parameterList, $paramName); - } elsif ($paramTypeIsPrimitive) { - if ($paramIDLType eq "boolean") { - push(@parameterList, "!!${paramName}"); - } else { - my $primitiveImplementationType = IDLTypeToImplementationType($paramIDLType); - push(@parameterList, "static_cast<${primitiveImplementationType}>(${paramName})"); - } - } else { - $CPPImplementationWebCoreIncludes{"COMPtr.h"} = 1; - - $needsCustom{"CanReturnEarly"} = 1; - - my $paramTypeCOMClassName = GetClassName($paramIDLType); - my $paramTypeImplementationWithoutNamespace = StripNamespace(IDLTypeToImplementationType($paramIDLType)); - my $ptrName = "ptrFor" . $codeGenerator->WK_ucfirst($paramName); - my $paramInit = " COMPtr<${paramTypeCOMClassName}> ${ptrName}(Query, ${paramName});\n"; - $paramInit .= " if (!${ptrName})\n"; - $paramInit .= " return E_NOINTERFACE;"; - push(@parameterInitialization, $paramInit); - push(@parameterList, "${ptrName}->impl${paramTypeImplementationWithoutNamespace}()"); - } - } - - push(@parameterList, "ec") if $raisesExceptions; - - my $implementationGetter = "impl${implementationClassWithoutNamespace}()"; - - my $callSigBegin = " "; - my $callSigMiddle = "${implementationGetter}->" . $codeGenerator->WK_lcfirst($functionName) . "(" . join(", ", @parameterList) . ")"; - my $callSigEnd = ";\n"; - - if (defined $needsCustom{"NodeToReturn"}) { - my $nodeToReturn = $needsCustom{"NodeToReturn"}; - $callSigBegin .= "if ("; - $callSigEnd = ")\n"; - $callSigEnd .= " *result = ${nodeToReturn};"; - } elsif (!$noReturn) { - my $returnTypeIsString = $codeGenerator->IsStringType($returnIDLType); - my $returnTypeIsPrimitive = $codeGenerator->IsPrimitiveType($returnIDLType); - - if ($returnTypeIsString) { - $callSigBegin .= "*result = WebCore::BString("; - $callSigEnd = ").release();\n"; - } elsif ($returnTypeIsPrimitive) { - my $primitiveCOMType = GetClassName($returnIDLType); - $callSigBegin .= "*result = static_cast<${primitiveCOMType}>("; - $callSigEnd = ");"; - } else { - $CPPImplementationIncludesAngle{"wtf/GetPtr.h"} = 1; - my $returnImplementationType = IDLTypeToImplementationType($returnIDLType); - my $returnTypeCOMInterfaceName = GetInterfaceName($returnIDLType); - $callSigBegin .= "${returnImplementationType}* resultImpl = WTF::getPtr("; - $callSigEnd = ");\n"; - $callSigEnd .= " if (!resultImpl)\n"; - $callSigEnd .= " return E_POINTER;\n\n"; - $callSigEnd .= " *result = to${returnTypeCOMInterfaceName}(resultImpl);"; - } - } - - push(@functionImplementation, $signature); - push(@functionImplementation, "{\n"); - unless ($noReturn) { - push(@functionImplementation, " if (!result)\n"); - push(@functionImplementation, " return E_POINTER;\n\n"); - push(@functionImplementation, " *result = 0;\n\n") if $needsCustom{"CanReturnEarly"}; - } - push(@functionImplementation, " WebCore::ExceptionCode ec = 0;\n") if $raisesExceptions; # FIXME: CHECK EXCEPTION AND DO SOMETHING WITH IT - push(@functionImplementation, join("\n", @parameterInitialization) . (@parameterInitialization > 0 ? "\n" : "")); - push(@functionImplementation, $callSigBegin . $callSigMiddle . $callSigEnd . "\n"); - push(@functionImplementation, " return S_OK;\n"); - push(@functionImplementation, "}\n\n"); - - return join("", @functionImplementation); -} - - -# ----------------------------------------------------------------------------- -# CPP Header -# ----------------------------------------------------------------------------- - -sub GenerateCPPHeader -{ - my ($object, $dataNode) = @_; - - my $IDLType = $dataNode->name; - my $implementationClass = IDLTypeToImplementationType($IDLType); - my $implementationClassWithoutNamespace = StripNamespace($implementationClass); - my $className = GetClassName($IDLType); - my $interfaceName = GetInterfaceName($IDLType); - - my $parentClassName = GetParentClass($dataNode); - my @otherInterfacesImplemented = GetAdditionalInterfaces($IDLType); - foreach my $otherInterface (@otherInterfacesImplemented) { - push(@additionalInterfaceDefinitions, $codeGenerator->ParseInterface($otherInterface)); - } - - # FIXME: strip whitespace from UUID - my $uuid = $dataNode->extendedAttributes->{"ImplementationUUID"} || die "All classes require an ImplementationUUID extended attribute."; - - my $numAttributes = @{$dataNode->attributes}; - my $numFunctions = @{$dataNode->functions}; - - # - Add default header template - @CPPHeaderHeader = @licenseTemplate; - push(@CPPHeaderHeader, "\n"); - - # - Header guards - - push(@CPPHeaderHeader, "#ifndef " . $className . "_h\n"); - push(@CPPHeaderHeader, "#define " . $className . "_h\n\n"); - - AddIncludesForTypeInCPPHeader($interfaceName); - AddIncludesForTypeInCPPHeader($parentClassName); - $CPPHeaderDontForwardDeclarations{$className} = 1; - $CPPHeaderDontForwardDeclarations{$interfaceName} = 1; - $CPPHeaderDontForwardDeclarations{$parentClassName} = 1; - - # -- Forward declare implementation type - push(@CPPHeaderContent, "namespace WebCore {\n"); - push(@CPPHeaderContent, " class ". StripNamespace($implementationClass) . ";\n"); - push(@CPPHeaderContent, "}\n\n"); - - # -- Start Class -- - my @parentsClasses = ($parentClassName, $interfaceName); - push(@parentsClasses, map { GetInterfaceName($_) } @otherInterfacesImplemented); - push(@CPPHeaderContent, "class __declspec(uuid(\"$uuid\")) ${className} : " . join(", ", map { "public $_" } @parentsClasses) . " {\n"); - - # Add includes for all additional interfaces to implement - map { AddIncludesForTypeInCPPHeader(GetInterfaceName($_)) } @otherInterfacesImplemented; - - # -- BASICS -- - # FIXME: The constructor and destructor should be protected, but the current design of - # createInstance requires them to be public. One solution is to friend the constructor - # of the top-level-class with every one of its child classes, but that requires information - # this script currently does not have, though possibly could determine. - push(@CPPHeaderContent, "public:\n"); - push(@CPPHeaderContent, " ${className}(${implementationClass}*);\n"); - push(@CPPHeaderContent, " virtual ~${className}();\n\n"); - - push(@CPPHeaderContent, "public:\n"); - push(@CPPHeaderContent, " static ${className}* createInstance(${implementationClass}*);\n\n"); - - push(@CPPHeaderContent, " // IUnknown\n"); - push(@CPPHeaderContent, " virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void** ppvObject);\n"); - push(@CPPHeaderContent, " virtual ULONG STDMETHODCALLTYPE AddRef() { return ${parentClassName}::AddRef(); }\n"); - push(@CPPHeaderContent, " virtual ULONG STDMETHODCALLTYPE Release() { return ${parentClassName}::Release(); }\n\n"); - - - # -- Parent Class Forwards -- - if (@{$dataNode->parents}) { - my %attributeNameSet = map {($_->signature->name, 1)} @{$dataNode->attributes}; - my %functionNameSet = map {($_->signature->name, 1)} @{$dataNode->functions}; - - my @parentLists = $codeGenerator->GetMethodsAndAttributesFromParentClasses($dataNode); - push(@CPPHeaderContent, "\n"); - foreach my $parentHash (@parentLists) { - - push(@CPPHeaderContent, " // " . GetInterfaceName($parentHash->{'name'}) . $DASHES . "\n"); - - my @attributeList = @{$parentHash->{'attributes'}}; - push(@CPPHeaderContent, " // Attributes\n"); - foreach my $attribute (@attributeList) { - # Don't forward an attribute that this class redefines. - next if $attributeNameSet{$attribute->signature->name}; - - AddForwardDeclarationsForTypeInCPPHeader($attribute->signature->type); - - my %attributes = GenerateCPPAttributeSignature($attribute, $className, { "NewLines" => 0, - "Indent" => 4, - "IncludeSemiColon" => 0, - "AddVirtualKeyword" => 1, - "UseClassName" => 0, - "Forwarder" => $parentClassName }); - push(@CPPHeaderContent, values(%attributes)); - } - - # Add attribute names to attribute names set in case other ancestors - # also define them. - $attributeNameSet{$_->signature->name} = 1 foreach @attributeList; - - push(@CPPHeaderContent, "\n"); - - my @functionList = @{$parentHash->{'functions'}}; - push(@CPPHeaderContent, " // Functions\n"); - foreach my $function (@functionList) { - # Don't forward a function that this class redefines. - next if $functionNameSet{$function->signature->name}; - - AddForwardDeclarationsForTypeInCPPHeader($function->signature->type); - AddForwardDeclarationsForTypeInCPPHeader($_->type) foreach (@{$function->parameters}); - - my $functionSig = GenerateCPPFunctionSignature($function, $className, { "NewLines" => 0, - "Indent" => 4, - "IncludeSemiColon" => 0, - "AddVirtualKeyword" => 1, - "UseClassName" => 0, - "Forwarder" => $parentClassName }); - - push(@CPPHeaderContent, $functionSig); - } - # Add functions names to functions names set in case other ancestors - # also define them. - $functionNameSet{$_->signature->name} = 1 foreach @functionList; - - push(@CPPHeaderContent, "\n"); - } - } - - # - Additional interfaces to implement - - foreach my $interfaceToImplement (@additionalInterfaceDefinitions) { - my $IDLTypeOfInterfaceToImplement = $interfaceToImplement->name; - my $nameOfInterfaceToImplement = GetInterfaceName($IDLTypeOfInterfaceToImplement); - my $numAttributesInInterface = @{$interfaceToImplement->attributes}; - my $numFunctionsInInterface = @{$interfaceToImplement->functions}; - - push(@CPPHeaderContent, " // ${nameOfInterfaceToImplement} ${DASHES}\n\n"); - - # - Add attribute getters/setters. - if ($numAttributesInInterface > 0) { - push(@CPPHeaderContent, " // Attributes\n\n"); - foreach my $attribute (@{$interfaceToImplement->attributes}) { - AddForwardDeclarationsForTypeInCPPHeader($attribute->signature->type); - - my %attributeSigs = GenerateCPPAttributeSignature($attribute, $className, { "NewLines" => 1, - "Indent" => 4, - "IncludeSemiColon" => 1, - "AddVirtualKeyword" => 1, - "UseClassName" => 0 }); - - push(@CPPHeaderContent, values(%attributeSigs)); - push(@CPPHeaderContent, "\n"); - } - } - - # - Add functions. - if ($numFunctionsInInterface > 0) { - push(@CPPHeaderContent, " // Functions\n\n"); - foreach my $function (@{$interfaceToImplement->functions}) { - AddForwardDeclarationsForTypeInCPPHeader($function->signature->type); - AddForwardDeclarationsForTypeInCPPHeader($_->type) foreach (@{$function->parameters}); - - my $functionSig = GenerateCPPFunctionSignature($function, $className, { "NewLines" => 1, - "Indent" => 4, - "IncludeSemiColon" => 1, - "AddVirtualKeyword" => 1, - "UseClassName" => 0 }); - - push(@CPPHeaderContent, $functionSig); - push(@CPPHeaderContent, "\n"); - } - } - } - - if ($numAttributes > 0 || $numFunctions > 0) { - push(@CPPHeaderContent, " // ${interfaceName} ${DASHES}\n\n"); - } - - # - Add constants COMING SOON - - # - Add attribute getters/setters. - if ($numAttributes > 0) { - push(@CPPHeaderContent, " // Attributes\n\n"); - foreach my $attribute (@{$dataNode->attributes}) { - AddForwardDeclarationsForTypeInCPPHeader($attribute->signature->type); - - my %attributeSigs = GenerateCPPAttributeSignature($attribute, $className, { "NewLines" => 1, - "Indent" => 4, - "IncludeSemiColon" => 1, - "AddVirtualKeyword" => 1, - "UseClassName" => 0 }); - - push(@CPPHeaderContent, values(%attributeSigs)); - push(@CPPHeaderContent, "\n"); - } - } - - # - Add functions. - if ($numFunctions > 0) { - push(@CPPHeaderContent, " // Functions\n\n"); - foreach my $function (@{$dataNode->functions}) { - AddForwardDeclarationsForTypeInCPPHeader($function->signature->type); - AddForwardDeclarationsForTypeInCPPHeader($_->type) foreach (@{$function->parameters}); - - my $functionSig = GenerateCPPFunctionSignature($function, $className, { "NewLines" => 1, - "Indent" => 4, - "IncludeSemiColon" => 1, - "AddVirtualKeyword" => 1, - "UseClassName" => 0 }); - - push(@CPPHeaderContent, $functionSig); - push(@CPPHeaderContent, "\n"); - } - } - - push(@CPPHeaderContent, " ${implementationClass}* impl${implementationClassWithoutNamespace}() const;\n"); - - if (@{$dataNode->parents} == 0) { - AddIncludesForTypeInCPPHeader("wtf/RefPtr", 1); - push(@CPPHeaderContent, "\n"); - push(@CPPHeaderContent, " ${implementationClass}* impl() const { return m_impl.get(); }\n\n"); - push(@CPPHeaderContent, "private:\n"); - push(@CPPHeaderContent, " RefPtr<${implementationClass}> m_impl;\n"); - } - - # -- End Class -- - push(@CPPHeaderContent, "};\n\n"); - - # -- Default Interface Creator -- - push(@CPPHeaderContent, "${interfaceName}* to${interfaceName}(${implementationClass}*);\n\n"); - - push(@CPPHeaderContent, "#endif // " . $className . "_h\n"); -} - - -# ----------------------------------------------------------------------------- -# CPP Implementation -# ----------------------------------------------------------------------------- - -sub GenerateCPPImplementation -{ - my ($object, $dataNode) = @_; - - my $IDLType = $dataNode->name; - my $implementationClass = IDLTypeToImplementationType($IDLType); - my $implementationClassWithoutNamespace = StripNamespace($implementationClass); - my $className = GetClassName($IDLType); - my $interfaceName = GetInterfaceName($IDLType); - - my $parentClassName = GetParentClass($dataNode); - my $isBaseClass = (@{$dataNode->parents} == 0); - - my $uuid = $dataNode->extendedAttributes->{"ImplementationUUID"} || die "All classes require an ImplementationUUID extended attribute."; - - my $numAttributes = @{$dataNode->attributes}; - my $numFunctions = @{$dataNode->functions}; - - # - Add default header template - @CPPImplementationHeader = @licenseTemplate; - push(@CPPImplementationHeader, "\n"); - - push(@CPPImplementationHeader, "#include \"config.h\"\n"); - push(@CPPImplementationHeader, "#include \"WebKitDLL.h\"\n"); - push(@CPPImplementationHeader, "#include " . ($className eq "GEN_DOMImplementation" ? "\"GEN_DOMDOMImplementation.h\"" : "\"${className}.h\"") . "\n"); - $CPPImplementationDontIncludes{"${className}.h"} = 1; - $CPPImplementationWebCoreIncludes{"${implementationClassWithoutNamespace}.h"} = 1; - - # -- Constructor -- - push(@CPPImplementationContent, "${className}::${className}(${implementationClass}* impl)\n"); - if ($isBaseClass) { - push(@CPPImplementationContent, " : m_impl(impl)\n"); - push(@CPPImplementationContent, "{\n"); - push(@CPPImplementationContent, " ASSERT_ARG(impl, impl);\n"); - push(@CPPImplementationContent, "}\n\n"); - } else { - push(@CPPImplementationContent, " : ${parentClassName}(impl)\n"); - push(@CPPImplementationContent, "{\n"); - push(@CPPImplementationContent, "}\n\n"); - } - - # -- Destructor -- - push(@CPPImplementationContent, "${className}::~${className}()\n"); - push(@CPPImplementationContent, "{\n"); - if ($isBaseClass) { - $CPPImplementationIncludes{"DOMCreateInstance.h"} = 1; - push(@CPPImplementationContent, " removeDOMWrapper(impl());\n"); - } - push(@CPPImplementationContent, "}\n\n"); - - push(@CPPImplementationContent, "${implementationClass}* ${className}::impl${implementationClassWithoutNamespace}() const\n"); - push(@CPPImplementationContent, "{\n"); - push(@CPPImplementationContent, " return static_cast<${implementationClass}*>(impl());\n"); - push(@CPPImplementationContent, "}\n\n"); - - # Base classes must implement the createInstance method externally. - if (@{$dataNode->parents} != 0) { - push(@CPPImplementationContent, "${className}* ${className}::createInstance(${implementationClass}* impl)\n"); - push(@CPPImplementationContent, "{\n"); - push(@CPPImplementationContent, " return static_cast<${className}*>(${parentClassName}::createInstance(impl));\n"); - push(@CPPImplementationContent, "}\n"); - } - - push(@CPPImplementationContent, "// IUnknown $DASHES\n\n"); - - # -- QueryInterface -- - push(@CPPImplementationContent, "HRESULT STDMETHODCALLTYPE ${className}::QueryInterface(REFIID riid, void** ppvObject)\n"); - push(@CPPImplementationContent, "{\n"); - push(@CPPImplementationContent, " *ppvObject = 0;\n"); - push(@CPPImplementationContent, " if (IsEqualGUID(riid, IID_${interfaceName}))\n"); - push(@CPPImplementationContent, " *ppvObject = reinterpret_cast<${interfaceName}*>(this);\n"); - push(@CPPImplementationContent, " else if (IsEqualGUID(riid, __uuidof(${className})))\n"); - push(@CPPImplementationContent, " *ppvObject = reinterpret_cast<${className}*>(this);\n"); - push(@CPPImplementationContent, " else\n"); - push(@CPPImplementationContent, " return ${parentClassName}::QueryInterface(riid, ppvObject);\n\n"); - push(@CPPImplementationContent, " AddRef();\n"); - push(@CPPImplementationContent, " return S_OK;\n"); - push(@CPPImplementationContent, "}\n\n"); - - # - Additional interfaces to implement - - foreach my $interfaceToImplement (@additionalInterfaceDefinitions) { - my $IDLTypeOfInterfaceToImplement = $interfaceToImplement->name; - my $nameOfInterfaceToImplement = GetInterfaceName($IDLTypeOfInterfaceToImplement); - my $numAttributesInInterface = @{$interfaceToImplement->attributes}; - my $numFunctionsInInterface = @{$interfaceToImplement->functions}; - - push(@CPPImplementationContent, " // ${nameOfInterfaceToImplement} ${DASHES}\n\n"); - - if ($numAttributesInInterface > 0) { - push(@CPPImplementationContent, "// Attributes\n\n"); - foreach my $attribute (@{$interfaceToImplement->attributes}) { - # FIXME: Do this in one step. - # FIXME: Implement exception handling. - - AddIncludesForTypeInCPPImplementation($attribute->signature->type); - - my %attributes = GenerateCPPAttribute($attribute, $className, $implementationClass, $IDLType); - push(@CPPImplementationContent, values(%attributes)); - } - } - - # - Add functions. - if ($numFunctionsInInterface > 0) { - push(@CPPImplementationContent, "// Functions\n\n"); - - foreach my $function (@{$interfaceToImplement->functions}) { - my $functionImplementation = GenerateCPPFunction($function, $className, $implementationClass); - push(@CPPImplementationContent, $functionImplementation); - } - } - } - - push(@CPPImplementationContent, "// ${interfaceName} $DASHES\n\n"); - - # - Add attribute getters/setters. - if ($numAttributes > 0) { - push(@CPPImplementationContent, "// Attributes\n\n"); - foreach my $attribute (@{$dataNode->attributes}) { - # FIXME: do this in one step - my $hasSetterException = @{$attribute->setterExceptions}; - my $hasGetterException = @{$attribute->getterExceptions}; - - AddIncludesForTypeInCPPImplementation($attribute->signature->type); - - my %attributes = GenerateCPPAttribute($attribute, $className, $implementationClass, $IDLType); - push(@CPPImplementationContent, values(%attributes)); - } - } - - # - Add functions. - if ($numFunctions > 0) { - push(@CPPImplementationContent, "// Functions\n\n"); - - foreach my $function (@{$dataNode->functions}) { - my $functionImplementation = GenerateCPPFunction($function, $className, $implementationClass); - push(@CPPImplementationContent, $functionImplementation); - } - } - - # - Default implementation for interface creator. - # FIXME: add extended attribute to add custom implementation if necessary. - push(@CPPImplementationContent, "${interfaceName}* to${interfaceName}(${implementationClass}* impl)\n"); - push(@CPPImplementationContent, "{\n"); - push(@CPPImplementationContent, " return ${className}::createInstance(impl);\n"); - push(@CPPImplementationContent, "}\n"); -} - -sub WriteData -{ - my ($object, $name, $pureInterface) = @_; - - # -- IDL -- - my $IDLFileName = "$outputDir/I" . $TEMP_PREFIX . "DOM" . $name . ".idl"; - unlink($IDLFileName); - - # Write to output IDL. - open(OUTPUTIDL, ">$IDLFileName") or die "Couldn't open file $IDLFileName"; - - # Add header - print OUTPUTIDL @IDLHeader; - - # Add forward declarations and imorts - delete $IDLForwardDeclarations{keys(%IDLDontForwardDeclare)}; - delete $IDLImports{keys(%IDLDontImport)}; - - print OUTPUTIDL map { "cpp_quote(\"interface $_;\")\n" } sort keys(%IDLForwardDeclarations); - print OUTPUTIDL "\n"; - - print OUTPUTIDL map { "interface $_;\n" } sort keys(%IDLForwardDeclarations); - print OUTPUTIDL "\n"; - print OUTPUTIDL "#ifndef DO_NO_IMPORTS\n"; - print OUTPUTIDL map { ($_ eq "IGEN_DOMImplementation") ? "import \"IGEN_DOMDOMImplementation.idl\";\n" : "import \"$_.idl\";\n" } sort keys(%IDLImports); - print OUTPUTIDL "#endif\n"; - print OUTPUTIDL "\n"; - - # Add content - print OUTPUTIDL @IDLContent; - - close(OUTPUTIDL); - - @IDLHeader = (); - @IDLContent = (); - - if ($pureInterface) { - my $CPPInterfaceHeaderFileName = "$outputDir/" . $TEMP_PREFIX . "DOM" . $name . ".h"; - unlink($CPPInterfaceHeaderFileName); - - open(OUTPUTCPPInterfaceHeader, ">$CPPInterfaceHeaderFileName") or die "Couldn't open file $CPPInterfaceHeaderFileName"; - - print OUTPUTCPPInterfaceHeader @CPPInterfaceHeader; - - close(OUTPUTCPPInterfaceHeader); - - @CPPInterfaceHeader = (); - } else { - my $CPPHeaderFileName = "$outputDir/" . $TEMP_PREFIX . "DOM" . $name . ".h"; - unlink($CPPHeaderFileName); - - # -- CPP Header -- - open(OUTPUTCPPHeader, ">$CPPHeaderFileName") or die "Couldn't open file $CPPHeaderFileName"; - - # Add header - print OUTPUTCPPHeader @CPPHeaderHeader; - - # Add includes - print OUTPUTCPPHeader map { ($_ eq "GEN_DOMImplementation.h") ? "#include \"GEN_DOMDOMImplementation.h\"\n" : "#include \"$_\"\n" } sort keys(%CPPHeaderIncludes); - print OUTPUTCPPHeader map { "#include <$_>\n" } sort keys(%CPPHeaderIncludesAngle); - - foreach my $dontDeclare (keys(%CPPHeaderDontForwardDeclarations)) { - delete $CPPHeaderForwardDeclarations{$dontDeclare} if ($CPPHeaderForwardDeclarations{$dontDeclare}); - } - print OUTPUTCPPHeader "\n"; - print OUTPUTCPPHeader map { "interface $_;\n" } sort keys(%CPPHeaderForwardDeclarations); - print OUTPUTCPPHeader "\n"; - - # Add content - print OUTPUTCPPHeader @CPPHeaderContent; - - close(OUTPUTCPPHeader); - - @CPPHeaderHeader = (); - @CPPHeaderContent = (); - - - # -- CPP Implementation -- - my $CPPImplementationFileName = "$outputDir/" . $TEMP_PREFIX . "DOM" . $name . ".cpp"; - unlink($CPPImplementationFileName); - - open(OUTPUTCPPImplementation, ">$CPPImplementationFileName") or die "Couldn't open file $CPPImplementationFileName"; - - # Add header - print OUTPUTCPPImplementation @CPPImplementationHeader; - print OUTPUTCPPImplementation "\n"; - - # Add includes - foreach my $dontInclude (keys(%CPPImplementationDontIncludes)) { - delete $CPPImplementationIncludes{$dontInclude} if ($CPPImplementationIncludes{$dontInclude}); - } - print OUTPUTCPPImplementation map { ($_ eq "GEN_DOMImplementation.h") ? "#include \"GEN_DOMDOMImplementation.h\"\n" : "#include \"$_\"\n" } sort keys(%CPPImplementationIncludes); - print OUTPUTCPPImplementation map { "#include <$_>\n" } sort keys(%CPPImplementationIncludesAngle); - print OUTPUTCPPImplementation "\n"; - - print OUTPUTCPPImplementation "#pragma warning(push, 0)\n"; - print OUTPUTCPPImplementation map { "#include <WebCore/$_>\n" } sort keys(%CPPImplementationWebCoreIncludes); - print OUTPUTCPPImplementation "#pragma warning(pop)\n"; - - # Add content - print OUTPUTCPPImplementation @CPPImplementationContent; - - close(OUTPUTCPPImplementation); - - @CPPImplementationHeader = (); - @CPPImplementationContent = (); - } -} - -1; diff --git a/WebCore/bindings/scripts/CodeGeneratorJS.pm b/WebCore/bindings/scripts/CodeGeneratorJS.pm index 6ccf739..7a55a3d 100644 --- a/WebCore/bindings/scripts/CodeGeneratorJS.pm +++ b/WebCore/bindings/scripts/CodeGeneratorJS.pm @@ -37,6 +37,8 @@ my @implContentHeader = (); my @implContent = (); my %implIncludes = (); my @depsContent = (); +my $numCachedAttributes = 0; +my $currentCachedAttribute = 0; # Default .h template my $headerTemplate = << "EOF"; @@ -132,15 +134,7 @@ sub GetParentClassName my $dataNode = shift; return $dataNode->extendedAttributes->{"LegacyParent"} if $dataNode->extendedAttributes->{"LegacyParent"}; - if (@{$dataNode->parents} eq 0) { - # FIXME: SVG types requiring a context() pointer do not have enough - # space to hold a globalObject pointer as well w/o hitting the CELL_SIZE limit. - # This could be fixed by moving context() into the various impl() classes. - # Until then, we special case these SVG bindings and allow them to return - # the wrong prototypes and constructors during x-frame access. See bug 27088. - return "DOMObjectWithSVGContext" if IsSVGTypeNeedingContextParameter($dataNode->name); - return "DOMObjectWithGlobalPointer"; - } + return "DOMObjectWithGlobalPointer" if (@{$dataNode->parents} eq 0); return "JS" . $codeGenerator->StripModule($dataNode->parents(0)); } @@ -169,16 +163,6 @@ sub IndexGetterReturnsStrings return 0; } -sub CreateSVGContextInterfaceName -{ - my $type = shift; - - return $type if $codeGenerator->IsSVGAnimatedType($type); - return "SVGPathSeg" if $type =~ /^SVGPathSeg/ and $type ne "SVGPathSegList"; - - return ""; -} - sub AddIncludesForType { my $type = $codeGenerator->StripModule(shift); @@ -491,7 +475,6 @@ sub GenerateHeader my $hasParent = $hasLegacyParent || $hasRealParent; my $parentClassName = GetParentClassName($dataNode); my $conditional = $dataNode->extendedAttributes->{"Conditional"}; - my $needsSVGContext = IsSVGTypeNeedingContextParameter($interfaceName); my $eventTarget = $dataNode->extendedAttributes->{"EventTarget"}; my $needsMarkChildren = $dataNode->extendedAttributes->{"CustomMarkFunction"} || $dataNode->extendedAttributes->{"EventTarget"}; @@ -511,8 +494,7 @@ sub GenerateHeader if ($hasParent) { $headerIncludes{"$parentClassName.h"} = 1; } else { - $headerIncludes{"DOMObjectWithSVGContext.h"} = $needsSVGContext; - $headerIncludes{"JSDOMBinding.h"} = !$needsSVGContext; + $headerIncludes{"JSDOMBinding.h"} = 1; $headerIncludes{"<runtime/JSGlobalObject.h>"} = 1; $headerIncludes{"<runtime/ObjectPrototype.h>"} = 1; } @@ -559,14 +541,12 @@ sub GenerateHeader push(@headerContent, " $className(NonNullPassRefPtr<JSC::Structure>, PassRefPtr<$implType>, JSDOMWindowShell*);\n"); } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) { push(@headerContent, " $className(NonNullPassRefPtr<JSC::Structure>, PassRefPtr<$implType>);\n"); - } elsif (IsSVGTypeNeedingContextParameter($implClassName)) { - push(@headerContent, " $className(NonNullPassRefPtr<JSC::Structure>, JSDOMGlobalObject*, PassRefPtr<$implType>, SVGElement* context);\n"); } else { push(@headerContent, " $className(NonNullPassRefPtr<JSC::Structure>, JSDOMGlobalObject*, PassRefPtr<$implType>);\n"); } # Destructor - push(@headerContent, " virtual ~$className();\n") if (!$hasParent or $eventTarget or $interfaceName eq "Document" or $interfaceName eq "DOMWindow"); + push(@headerContent, " virtual ~$className();\n") if (!$hasParent or $eventTarget or $interfaceName eq "DOMWindow"); # Prototype push(@headerContent, " static JSC::JSObject* createPrototype(JSC::ExecState*, JSC::JSGlobalObject*);\n") unless ($dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"}); @@ -574,7 +554,8 @@ sub GenerateHeader $implIncludes{"${className}Custom.h"} = 1 if $dataNode->extendedAttributes->{"CustomHeader"} || $dataNode->extendedAttributes->{"CustomPutFunction"} || $dataNode->extendedAttributes->{"DelegatingPutFunction"}; my $hasGetter = $numAttributes > 0 - || $dataNode->extendedAttributes->{"GenerateConstructor"} + || !($dataNode->extendedAttributes->{"OmitConstructor"} + || $dataNode->extendedAttributes->{"CustomConstructor"}) || $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"} @@ -625,7 +606,7 @@ sub GenerateHeader push(@headerContent, " static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype)\n" . " {\n" . - " return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags));\n" . + " return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount);\n" . " }\n\n"); # markChildren function @@ -645,7 +626,7 @@ sub GenerateHeader # Custom getPropertyNames function exists on DOMWindow if ($interfaceName eq "DOMWindow") { - push(@headerContent, " virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&);\n"); + push(@headerContent, " virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n"); $structureFlags{"JSC::OverridesGetPropertyNames"} = 1; } @@ -654,7 +635,7 @@ sub GenerateHeader # Custom getOwnPropertyNames function if ($dataNode->extendedAttributes->{"CustomGetPropertyNames"} || $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) { - push(@headerContent, " virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&);\n"); + push(@headerContent, " virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n"); $structureFlags{"JSC::OverridesGetPropertyNames"} = 1; } @@ -677,7 +658,7 @@ sub GenerateHeader } # Constructor object getter - push(@headerContent, " static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*);\n") if $dataNode->extendedAttributes->{"GenerateConstructor"}; + push(@headerContent, " static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*);\n") if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})); my $numCustomFunctions = 0; my $numCustomAttributes = 0; @@ -689,9 +670,17 @@ sub GenerateHeader $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"JSCCustom"}; $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"CustomGetter"} || $attribute->signature->extendedAttributes->{"JSCCustomGetter"}; $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"CustomSetter"} || $attribute->signature->extendedAttributes->{"JSCCustomSetter"}; + if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) { + push(@headerContent, " static const unsigned " . $attribute->signature->name . "Slot = $numCachedAttributes + Base::AnonymousSlotCount;\n"); + $numCachedAttributes++; + } } } + if ($numCachedAttributes > 0) { + push(@headerContent, " using $parentClassName" . "::putAnonymousValue;\n"); + push(@headerContent, " using $parentClassName" . "::getAnonymousValue;\n"); + } if ($numCustomAttributes > 0) { push(@headerContent, "\n // Custom attributes\n"); @@ -738,6 +727,12 @@ sub GenerateHeader push(@headerContent, " }\n"); } + # anonymous slots + if ($numCachedAttributes) { + push(@headerContent, "public:\n"); + push(@headerContent, " static const unsigned AnonymousSlotCount = $numCachedAttributes + Base::AnonymousSlotCount;\n"); + } + # structure flags push(@headerContent, "protected:\n"); push(@headerContent, " static const unsigned StructureFlags = "); @@ -781,7 +776,7 @@ sub GenerateHeader if (!$hasParent || $dataNode->extendedAttributes->{"GenerateToJS"} || $dataNode->extendedAttributes->{"CustomToJS"}) { if ($podType) { - push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, JSSVGPODTypeWrapper<$podType>*, SVGElement* context);\n"); + push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, JSSVGPODTypeWrapper<$podType>*, SVGElement*);\n"); } elsif (IsSVGTypeNeedingContextParameter($implClassName)) { push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, $implType*, SVGElement* context);\n"); } else { @@ -830,7 +825,7 @@ sub GenerateHeader push(@headerContent, " static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype)\n" . " {\n" . - " return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags));\n" . + " return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount);\n" . " }\n"); if ($dataNode->extendedAttributes->{"DelegatingPrototypePutFunction"}) { push(@headerContent, " virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);\n"); @@ -860,7 +855,7 @@ sub GenerateHeader } } - if ($numAttributes > 0 || $dataNode->extendedAttributes->{"GenerateConstructor"}) { + if ($numAttributes > 0 || !($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) { 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" : ""); @@ -871,7 +866,7 @@ sub GenerateHeader } } - if ($dataNode->extendedAttributes->{"GenerateConstructor"}) { + 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"); } @@ -940,7 +935,7 @@ sub GenerateImplementation # - Add all attributes in a hashtable definition my $numAttributes = @{$dataNode->attributes}; - $numAttributes++ if $dataNode->extendedAttributes->{"GenerateConstructor"}; + $numAttributes++ if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})); if ($numAttributes > 0) { my $hashSize = $numAttributes; @@ -981,7 +976,7 @@ sub GenerateImplementation } } - if ($dataNode->extendedAttributes->{"GenerateConstructor"}) { + if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) { push(@hashKeys, "constructor"); my $getter = "js" . $interfaceName . "Constructor"; push(@hashValue1, $getter); @@ -999,7 +994,7 @@ sub GenerateImplementation my $numFunctions = @{$dataNode->functions}; # - Add all constants - if ($dataNode->extendedAttributes->{"GenerateConstructor"}) { + if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) { $hashSize = $numConstants; $hashName = $className . "ConstructorTable"; @@ -1171,9 +1166,6 @@ sub GenerateImplementation my $podType = $dataNode->extendedAttributes->{"PODType"}; my $implType = $podType ? "JSSVGPODTypeWrapper<$podType> " : $implClassName; - my $needsSVGContext = IsSVGTypeNeedingContextParameter($implClassName); - my $parentNeedsSVGContext = ($needsSVGContext and $parentClassName =~ /SVG/); - # Constructor if ($interfaceName eq "DOMWindow") { AddIncludesForType("JSDOMWindowShell"); @@ -1184,16 +1176,19 @@ sub GenerateImplementation push(@implContent, "${className}::$className(NonNullPassRefPtr<Structure> structure, PassRefPtr<$implType> impl)\n"); push(@implContent, " : $parentClassName(structure, impl)\n"); } else { - my $contextArg = $needsSVGContext ? ", SVGElement* context" : ""; - push(@implContent, "${className}::$className(NonNullPassRefPtr<Structure> structure, JSDOMGlobalObject* globalObject, PassRefPtr<$implType> impl$contextArg)\n"); + push(@implContent, "${className}::$className(NonNullPassRefPtr<Structure> structure, JSDOMGlobalObject* globalObject, PassRefPtr<$implType> impl)\n"); if ($hasParent) { - push(@implContent, " : $parentClassName(structure, globalObject, impl" . ($parentNeedsSVGContext ? ", context" : "") . ")\n"); + push(@implContent, " : $parentClassName(structure, globalObject, impl)\n"); } else { - push(@implContent, " : $parentClassName(structure, globalObject" . ($needsSVGContext ? ", context" : "") . ")\n"); + push(@implContent, " : $parentClassName(structure, globalObject)\n"); push(@implContent, " , m_impl(impl)\n"); } } push(@implContent, "{\n"); + if ($numCachedAttributes > 0) { + push(@implContent, " for (unsigned i = Base::AnonymousSlotCount; i < AnonymousSlotCount; i++)\n"); + push(@implContent, " putAnonymousValue(i, JSValue());\n"); + } push(@implContent, "}\n\n"); # Destructor @@ -1210,29 +1205,15 @@ sub GenerateImplementation if ($interfaceName eq "Node") { push(@implContent, " forgetDOMNode(this, impl(), impl()->document());\n"); } else { - if ($podType) { - my $animatedType = $implClassName; - $animatedType =~ s/SVG/SVGAnimated/; - - # Special case for JSSVGNumber - if ($codeGenerator->IsSVGAnimatedType($animatedType) and $podType ne "float") { - push(@implContent, " JSSVGDynamicPODTypeWrapperCache<$podType, $animatedType>::forgetWrapper(m_impl.get());\n"); - } - } push(@implContent, " forgetDOMObject(this, impl());\n"); } + + push(@implContent, " JSSVGContextCache::forgetWrapper(this);\n") if IsSVGTypeNeedingContextParameter($implClassName); } push(@implContent, "}\n\n"); } - # Document needs a special destructor because it's a special case for caching. It needs - # its own special handling rather than relying on the caching that Node normally does. - if ($interfaceName eq "Document") { - push(@implContent, "${className}::~$className()\n"); - push(@implContent, "{\n forgetDOMObject(this, static_cast<${implClassName}*>(impl()));\n}\n\n"); - } - if ($needsMarkChildren && !$dataNode->extendedAttributes->{"CustomMarkFunction"}) { push(@implContent, "void ${className}::markChildren(MarkStack& markStack)\n"); push(@implContent, "{\n"); @@ -1253,7 +1234,8 @@ sub GenerateImplementation } my $hasGetter = $numAttributes > 0 - || $dataNode->extendedAttributes->{"GenerateConstructor"} + || !($dataNode->extendedAttributes->{"OmitConstructor"} + || $dataNode->extendedAttributes->{"CustomConstructor"}) || $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"} @@ -1352,12 +1334,19 @@ sub GenerateImplementation push(@implContent, " return JS" . $constructorType . "::getConstructor(exec, castedThis);\n"); } elsif (!@{$attribute->getterExceptions}) { push(@implContent, " UNUSED_PARAM(exec);\n"); + my $cacheIndex = 0; + if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) { + $cacheIndex = $currentCachedAttribute; + $currentCachedAttribute++; + push(@implContent, " if (JSValue cachedValue = castedThis->getAnonymousValue(" . $className . "::" . $attribute->signature->name . "Slot))\n"); + push(@implContent, " return cachedValue;\n"); + } if ($podType) { push(@implContent, " $podType imp(*castedThis->impl());\n"); if ($podType eq "float") { # Special case for JSSVGNumber - push(@implContent, " return " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp", "castedThis") . ";\n"); + push(@implContent, " JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp", "castedThis") . ";\n"); } else { - push(@implContent, " return " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp.$implGetterFunctionName()", "castedThis") . ";\n"); + push(@implContent, " JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp.$implGetterFunctionName()", "castedThis") . ";\n"); } } else { push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n"); @@ -1376,11 +1365,15 @@ sub GenerateImplementation my $jsType = NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, $value, "castedThis"); if ($codeGenerator->IsSVGAnimatedType($type)) { push(@implContent, " RefPtr<$type> obj = $jsType;\n"); - push(@implContent, " return toJS(exec, castedThis->globalObject(), obj.get(), imp);\n"); + push(@implContent, " JSValue result = toJS(exec, castedThis->globalObject(), obj.get(), imp);\n"); } else { - push(@implContent, " return $jsType;\n"); + push(@implContent, " JSValue result = $jsType;\n"); } } + + push(@implContent, " castedThis->putAnonymousValue(" . $className . "::" . $attribute->signature->name . "Slot, result);\n") if ($attribute->signature->extendedAttributes->{"CachedAttribute"}); + push(@implContent, " return result;\n"); + } else { push(@implContent, " ExceptionCode ec = 0;\n"); if ($podType) { @@ -1404,20 +1397,13 @@ sub GenerateImplementation push(@implContent, "\n"); } - if ($dataNode->extendedAttributes->{"GenerateConstructor"}) { + 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, "{\n"); - if (IsSVGTypeNeedingContextParameter($interfaceName)) { - # FIXME: SVG bindings with a context pointer have no space to store a globalObject - # so we use deprecatedGlobalObjectForPrototype instead. - push(@implContent, " UNUSED_PARAM(slot);\n"); - push(@implContent, " return ${className}::getConstructor(exec, deprecatedGlobalObjectForPrototype(exec));\n"); - } else { - push(@implContent, " ${className}* domObject = static_cast<$className*>(asObject(slot.slotBase()));\n"); - push(@implContent, " return ${className}::getConstructor(exec, domObject->globalObject());\n"); - } + push(@implContent, " ${className}* domObject = static_cast<$className*>(asObject(slot.slotBase()));\n"); + push(@implContent, " return ${className}::getConstructor(exec, domObject->globalObject());\n"); push(@implContent, "}\n"); } } @@ -1491,16 +1477,7 @@ sub GenerateImplementation $implIncludes{"JSEventListener.h"} = 1; push(@implContent, " UNUSED_PARAM(exec);\n"); push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(static_cast<$className*>(thisObject)->impl());\n"); - if ($dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"}) { - push(@implContent, " JSDOMGlobalObject* globalObject = static_cast<$className*>(thisObject);\n"); - } else { - $implIncludes{"Frame.h"} = 1; - $implIncludes{"JSDOMGlobalObject.h"} = 1; - push(@implContent, " JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(imp->scriptExecutionContext(), exec);\n"); - push(@implContent, " if (!globalObject)\n"); - push(@implContent, " return;\n"); - } - push(@implContent, " imp->set$implSetterFunctionName(globalObject->createJSAttributeEventListener(value));\n"); + push(@implContent, " imp->set$implSetterFunctionName(createJSAttributeEventListener(exec, value));\n"); } elsif ($attribute->signature->type =~ /Constructor$/) { my $constructorType = $attribute->signature->type; $constructorType =~ s/Constructor$//; @@ -1511,16 +1488,17 @@ sub GenerateImplementation push(@implContent, " // Shadowing a built-in object\n"); push(@implContent, " static_cast<$className*>(thisObject)->putDirect(Identifier(exec, \"$name\"), value);\n"); } else { + push(@implContent, " $className* castedThisObj = static_cast<$className*>(thisObject);\n"); + push(@implContent, " $implType* imp = static_cast<$implType*>(castedThisObj->impl());\n"); if ($podType) { - push(@implContent, " $podType imp(*static_cast<$className*>(thisObject)->impl());\n"); + push(@implContent, " $podType podImp(*imp);\n"); if ($podType eq "float") { # Special case for JSSVGNumber - push(@implContent, " imp = " . JSValueToNative($attribute->signature, "value") . ";\n"); + push(@implContent, " podImp = " . JSValueToNative($attribute->signature, "value") . ";\n"); } else { - push(@implContent, " imp.set$implSetterFunctionName(" . JSValueToNative($attribute->signature, "value") . ");\n"); + push(@implContent, " podImp.set$implSetterFunctionName(" . JSValueToNative($attribute->signature, "value") . ");\n"); } - push(@implContent, " static_cast<$className*>(thisObject)->impl()->commitChange(imp, static_cast<$className*>(thisObject)->context());\n"); + push(@implContent, " imp->commitChange(podImp, castedThisObj);\n"); } else { - push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(static_cast<$className*>(thisObject)->impl());\n"); my $nativeValue = JSValueToNative($attribute->signature, "value"); push(@implContent, " ExceptionCode ec = 0;\n") if @{$attribute->setterExceptions}; my $reflect = $attribute->signature->extendedAttributes->{"Reflect"}; @@ -1536,10 +1514,8 @@ sub GenerateImplementation push(@implContent, ", ec") if @{$attribute->setterExceptions}; push(@implContent, ");\n"); push(@implContent, " setDOMException(exec, ec);\n") if @{$attribute->setterExceptions}; - if (IsSVGTypeNeedingContextParameter($implClassName)) { - push(@implContent, " if (static_cast<$className*>(thisObject)->context())\n"); - push(@implContent, " static_cast<$className*>(thisObject)->context()->svgAttributeChanged(static_cast<$className*>(thisObject)->impl()->associatedAttributeName());\n"); + push(@implContent, " JSSVGContextCache::propagateSVGDOMChange(castedThisObj, imp->associatedAttributeName());\n"); } } } @@ -1552,17 +1528,17 @@ sub GenerateImplementation } if (($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) && !$dataNode->extendedAttributes->{"CustomGetPropertyNames"}) { - push(@implContent, "void ${className}::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)\n"); + push(@implContent, "void ${className}::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)\n"); push(@implContent, "{\n"); if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) { push(@implContent, " for (unsigned i = 0; i < static_cast<${implClassName}*>(impl())->length(); ++i)\n"); push(@implContent, " propertyNames.add(Identifier::from(exec, i));\n"); } - push(@implContent, " Base::getOwnPropertyNames(exec, propertyNames);\n"); + push(@implContent, " Base::getOwnPropertyNames(exec, propertyNames, mode);\n"); push(@implContent, "}\n\n"); } - if ($dataNode->extendedAttributes->{"GenerateConstructor"}) { + if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) { push(@implContent, "JSValue ${className}::getConstructor(ExecState* exec, JSGlobalObject* globalObject)\n{\n"); push(@implContent, " return getDOMConstructor<${className}Constructor>(exec, static_cast<JSDOMGlobalObject*>(globalObject));\n"); push(@implContent, "}\n\n"); @@ -1602,15 +1578,31 @@ sub GenerateImplementation push(@implContent, " return jsUndefined();\n"); } + # Special case for JSSVGLengthList / JSSVGTransformList / JSSVGPointList / JSSVGNumberList + # Instead of having JSSVG*Custom.cpp implementations for the SVGList interface for all of these + # classes, we directly forward the calls to JSSVGPODListCustom, which centralizes the otherwise + # duplicated code for the JSSVG*List classes mentioned above. + my $svgPODListType; + if ($implClassName =~ /SVG.*List/) { + $svgPODListType = $implClassName; + $svgPODListType =~ s/List$//; + $svgPODListType = "" unless $codeGenerator->IsPodType($svgPODListType); + + # Ignore additional (non-SVGList) SVGTransformList methods, that are not handled through JSSVGPODListCustom + $svgPODListType = "" if $functionImplementationName =~ /createSVGTransformFromMatrix/; + $svgPODListType = "" if $functionImplementationName =~ /consolidate/; + } + if ($function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"JSCCustom"}) { push(@implContent, " return castedThisObj->" . $functionImplementationName . "(exec, args);\n"); + } elsif ($svgPODListType) { + $implIncludes{"JS${svgPODListType}.h"} = 1; + $implIncludes{"JSSVGPODListCustom.h"} = 1; + push(@implContent, " return JSSVGPODListCustom::$functionImplementationName<$className, " . GetNativeType($svgPODListType) + . ">(castedThisObj, exec, args, to" . $svgPODListType . ");\n"); } else { - if ($podType) { - push(@implContent, " JSSVGPODTypeWrapper<$podType>* wrapper = castedThisObj->impl();\n"); - push(@implContent, " $podType imp(*wrapper);\n"); - } else { - push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(castedThisObj->impl());\n"); - } + push(@implContent, " $implType* imp = static_cast<$implType*>(castedThisObj->impl());\n"); + push(@implContent, " $podType podImp(*imp);\n") if $podType; my $numParameters = @{$function->parameters}; @@ -1630,7 +1622,7 @@ sub GenerateImplementation } my $paramIndex = 0; - my $functionString = "imp" . ($podType ? "." : "->") . $functionImplementationName . "("; + my $functionString = ($podType ? "podImp." : "imp->") . $functionImplementationName . "("; my $hasOptionalArguments = 0; @@ -1741,11 +1733,10 @@ sub GenerateImplementation if ($podType) { push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, JSSVGPODTypeWrapper<$podType>* object, SVGElement* context)\n"); } elsif (IsSVGTypeNeedingContextParameter($implClassName)) { - push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, $implType* object, SVGElement* context)\n"); + push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, $implType* object, SVGElement* context)\n"); } else { push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, $implType* object)\n"); } - push(@implContent, "{\n"); if ($podType) { push(@implContent, " return getDOMObjectWrapper<$className, JSSVGPODTypeWrapper<$podType> >(exec, globalObject, object, context);\n"); @@ -1803,11 +1794,7 @@ sub GenerateImplementationFunctionCall() if ($function->signature->type eq "void") { push(@implContent, $indent . "$functionString;\n"); push(@implContent, $indent . "setDOMException(exec, ec);\n") if @{$function->raisesExceptions}; - - if ($podType) { - push(@implContent, $indent . "wrapper->commitChange(imp, castedThisObj->context());\n"); - } - + push(@implContent, $indent . "imp->commitChange(podImp, castedThisObj);\n") if $podType; push(@implContent, $indent . "return jsUndefined();\n"); } else { push(@implContent, "\n" . $indent . "JSC::JSValue result = " . NativeToJSValue($function->signature, 1, $implClassName, "", $functionString, "castedThisObj") . ";\n"); @@ -1816,7 +1803,7 @@ sub GenerateImplementationFunctionCall() if ($podType and not $function->signature->extendedAttributes->{"Immutable"}) { # Immutable methods do not commit changes back to the instance, thus producing # a new instance rather than mutating existing one. - push(@implContent, $indent . "wrapper->commitChange(imp, castedThisObj->context());\n"); + push(@implContent, $indent . "imp->commitChange(podImp, castedThisObj);\n"); } push(@implContent, $indent . "return result;\n"); @@ -1840,10 +1827,12 @@ my %nativeType = ( "CompareHow" => "Range::CompareHow", "DOMString" => "const UString&", "NodeFilter" => "RefPtr<NodeFilter>", + "SVGAngle" => "SVGAngle", "SVGLength" => "SVGLength", "SVGMatrix" => "TransformationMatrix", "SVGNumber" => "float", "SVGPaintType" => "SVGPaint::SVGPaintType", + "SVGPreserveAspectRatio" => "SVGPreserveAspectRatio", "SVGPoint" => "FloatPoint", "SVGRect" => "FloatRect", "SVGTransform" => "SVGTransform", @@ -1853,6 +1842,8 @@ my %nativeType = ( "long" => "int", "unsigned long" => "unsigned", "unsigned short" => "unsigned short", + "long long" => "long long", + "unsigned long long" => "unsigned long long", ); sub GetNativeType @@ -1876,7 +1867,9 @@ sub JSValueToNative return "$value.toNumber(exec)" if $type eq "double"; return "$value.toFloat(exec)" if $type eq "float" or $type eq "SVGNumber"; return "$value.toInt32(exec)" if $type eq "unsigned long" or $type eq "long" or $type eq "unsigned short"; + return "static_cast<$type>($value.toInteger(exec))" if $type eq "long long" or $type eq "unsigned long long"; + return "valueToDate(exec, $value)" if $type eq "Date"; return "static_cast<Range::CompareHow>($value.toInt32(exec))" if $type eq "CompareHow"; return "static_cast<SVGPaint::SVGPaintType>($value.toInt32(exec))" if $type eq "SVGPaintType"; @@ -1886,7 +1879,7 @@ sub JSValueToNative return "$value.toString(exec)"; } - if ($type eq "SerializedScriptValue") { + if ($type eq "SerializedScriptValue" or $type eq "any") { $implIncludes{"SerializedScriptValue.h"} = 1; return "SerializedScriptValue::create(exec, $value)"; } @@ -1914,7 +1907,11 @@ sub NativeToJSValue my $type = $codeGenerator->StripModule($signature->type); return "jsBoolean($value)" if $type eq "boolean"; - + + # Need to check Date type before IsPrimitiveType(). + if ($type eq "Date") { + return "jsDateOrNull(exec, $value)"; + } if ($codeGenerator->IsPrimitiveType($type) or $type eq "SVGPaintType" or $type eq "DOMTimeStamp") { $implIncludes{"<runtime/JSNumberCell.h>"} = 1; return "jsNumber(exec, $value)"; @@ -1934,9 +1931,7 @@ sub NativeToJSValue return "jsString(exec, $value)"; } - # Some SVG bindings don't have space to store a globalObject pointer, for those, we use the deprecatedGlobalObjectForPrototype hack for now. - my $globalObject = IsSVGTypeNeedingContextParameter($implClassName) ? "deprecatedGlobalObjectForPrototype(exec)" : "$thisValue->globalObject()"; - + my $globalObject = "$thisValue->globalObject()"; if ($codeGenerator->IsPodType($type)) { $implIncludes{"JS$type.h"} = 1; @@ -1954,25 +1949,16 @@ sub NativeToJSValue and $codeGenerator->IsPodTypeWithWriteableProperties($type) and not defined $signature->extendedAttributes->{"Immutable"}) { if ($codeGenerator->IsPodType($implClassName)) { - return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName>::create($value, $thisValue->impl()).get(), $thisValue->context())"; + return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName>::create($value, $thisValue->impl()).get(), JSSVGContextCache::svgContextForDOMObject(castedThis))"; } else { return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName>::create(imp, &${implClassName}::$getter, &${implClassName}::$setter).get(), imp)"; } } if ($implClassNameForValueConversion eq "") { - # SVGZoomEvent has no context() pointer, and is also not an SVGElement. - # This is not a problem, because SVGZoomEvent has no read/write properties. - return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), 0)" if $implClassName eq "SVGZoomEvent"; - - if (IsSVGTypeNeedingContextParameter($implClassName)) { - return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), castedThisObj->context())" if $inFunctionCall; - return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), $thisValue->context())"; - } else { - return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), imp)"; - } - } else { # These classes, always have a m_context pointer! - return "toJS(exec, $globalObject, JSSVGDynamicPODTypeWrapperCache<$nativeType, $implClassNameForValueConversion>::lookupOrCreateWrapper(imp, &${implClassNameForValueConversion}::$getter, &${implClassNameForValueConversion}::$setter).get(), $thisValue->context())"; + return "toJS(exec, $globalObject, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), 0 /* no context on purpose */)"; + } else { + return "toJS(exec, $globalObject, JSSVGDynamicPODTypeWrapperCache<$nativeType, $implClassNameForValueConversion>::lookupOrCreateWrapper(imp, &${implClassNameForValueConversion}::$getter, &${implClassNameForValueConversion}::$setter).get(), JSSVGContextCache::svgContextForDOMObject(castedThis));" } } @@ -1998,9 +1984,9 @@ sub NativeToJSValue $joinedName = $type; $joinedName =~ s/Abs|Rel//; $implIncludes{"$joinedName.h"} = 1; - } elsif ($type eq "SerializedScriptValue") { - $implIncludes{"$type.h"} = 1; - return "$value->deserialize(exec)"; + } elsif ($type eq "SerializedScriptValue" or $type eq "any") { + $implIncludes{"SerializedScriptValue.h"} = 1; + return "$value ? $value->deserialize(exec, castedThis->globalObject()) : jsNull()"; } else { # Default, include header with same name. $implIncludes{"JS$type.h"} = 1; @@ -2010,7 +1996,7 @@ sub NativeToJSValue return $value if $codeGenerator->IsSVGAnimatedType($type); if (IsSVGTypeNeedingContextParameter($type)) { - my $contextPtr = IsSVGTypeNeedingContextParameter($implClassName) ? "$thisValue->context()" : "imp"; + my $contextPtr = IsSVGTypeNeedingContextParameter($implClassName) ? "JSSVGContextCache::svgContextForDOMObject(castedThis)" : "imp"; return "toJS(exec, $globalObject, WTF::getPtr($value), $contextPtr)"; } @@ -2295,7 +2281,7 @@ public: static PassRefPtr<Structure> createStructure(JSValue proto) { - return Structure::create(proto, TypeInfo(ObjectType, StructureFlags)); + return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); } protected: diff --git a/WebCore/bindings/scripts/CodeGeneratorObjC.pm b/WebCore/bindings/scripts/CodeGeneratorObjC.pm index 91248c5..698b4f5 100644 --- a/WebCore/bindings/scripts/CodeGeneratorObjC.pm +++ b/WebCore/bindings/scripts/CodeGeneratorObjC.pm @@ -66,7 +66,7 @@ my %nativeObjCTypeHash = ("URL" => 1, "Color" => 1); my %baseTypeHash = ("Object" => 1, "Node" => 1, "NodeList" => 1, "NamedNodeMap" => 1, "DOMImplementation" => 1, "Event" => 1, "CSSRule" => 1, "CSSValue" => 1, "StyleSheet" => 1, "MediaList" => 1, "Counter" => 1, "Rect" => 1, "RGBColor" => 1, "XPathExpression" => 1, "XPathResult" => 1, - "NodeIterator" => 1, "TreeWalker" => 1, "AbstractView" => 1, + "NodeIterator" => 1, "TreeWalker" => 1, "AbstractView" => 1, "Blob" => 1, "SVGAngle" => 1, "SVGAnimatedAngle" => 1, "SVGAnimatedBoolean" => 1, "SVGAnimatedEnumeration" => 1, "SVGAnimatedInteger" => 1, "SVGAnimatedLength" => 1, "SVGAnimatedLengthList" => 1, "SVGAnimatedNumber" => 1, "SVGAnimatedNumberList" => 1, "SVGAnimatedPoints" => 1, @@ -316,6 +316,7 @@ sub GetClassName return "BOOL" if $name eq "boolean"; return "unsigned" if $name eq "unsigned long"; return "int" if $name eq "long"; + return "NSTimeInterval" if $name eq "Date"; return "DOMAbstractView" if $name eq "DOMWindow"; return $name if $codeGenerator->IsPrimitiveType($name) or $name eq "DOMImplementation" or $name eq "DOMTimeStamp"; @@ -1040,6 +1041,7 @@ sub GenerateImplementation $implIncludes{$classHeaderName . "Internal.h"} = 1; # FIXME: These includes are only needed when the class is a subclass of one of these polymorphic classes. + $implIncludes{"DOMBlobInternal.h"} = 1; $implIncludes{"DOMCSSRuleInternal.h"} = 1; $implIncludes{"DOMCSSValueInternal.h"} = 1; $implIncludes{"DOMEventInternal.h"} = 1; @@ -1221,7 +1223,7 @@ sub GenerateImplementation $getterContentTail .= ")"; } elsif ($attribute->signature->extendedAttributes->{"ConvertFromString"}) { $getterContentTail .= ".toInt()"; - } elsif ($codeGenerator->IsPodType($idlType)) { + } elsif ($codeGenerator->IsPodType($idlType) or $idlType eq "Date") { $getterContentHead = "kit($getterContentHead"; $getterContentTail .= ")"; } elsif (IsProtocolType($idlType) and $idlType ne "EventTarget") { @@ -1292,6 +1294,10 @@ sub GenerateImplementation push(@implContent, " ASSERT($argName);\n\n"); } + if ($idlType eq "Date") { + $arg = "core(" . $arg . ")"; + } + if ($podType) { # Special case for DOMSVGNumber if ($podType eq "float") { diff --git a/WebCore/bindings/scripts/CodeGeneratorV8.pm b/WebCore/bindings/scripts/CodeGeneratorV8.pm index 77e9512..305fdfd 100644 --- a/WebCore/bindings/scripts/CodeGeneratorV8.pm +++ b/WebCore/bindings/scripts/CodeGeneratorV8.pm @@ -265,15 +265,18 @@ sub GenerateHeader push(@headerContent, "#include <v8.h>\n"); push(@headerContent, "#include <wtf/HashMap.h>\n"); push(@headerContent, "#include \"StringHash.h\"\n"); - - push(@headerContent, "\nnamespace WebCore {\n\n"); - push(@headerContent, "class V8ClassIndex;\n"); + push(@headerContent, "#include \"V8Index.h\"\n"); + push(@headerContent, GetHeaderClassInclude($implClassName)); + push(@headerContent, "\nnamespace WebCore {\n"); push(@headerContent, "\nclass $className {\n"); + + my $toNativeReturnType = GetReturnTypeForToNative($interfaceName); push(@headerContent, <<END); public: static bool HasInstance(v8::Handle<v8::Value> value); static v8::Persistent<v8::FunctionTemplate> GetRawTemplate(); + static ${toNativeReturnType}* toNative(v8::Handle<v8::Object>); END if ($implClassName eq "DOMWindow") { @@ -282,6 +285,59 @@ END END } + my @enabledAtRuntime; + foreach my $function (@{$dataNode->functions}) { + 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&); +END + if ($attrExt->{"EnabledAtRuntime"}) { + push(@enabledAtRuntime, $function); + } + } + + if ($dataNode->extendedAttributes->{"CustomConstructor"} || $dataNode->extendedAttributes->{"CanBeConstructed"}) { + push(@headerContent, <<END); + static v8::Handle<v8::Value> constructorCallback(const v8::Arguments& args); +END + } + + foreach my $attribute (@{$dataNode->attributes}) { + my $name = $attribute->signature->name; + my $attrExt = $attribute->signature->extendedAttributes; + 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); +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); +END + } + if ($attrExt->{"EnabledAtRuntime"}) { + push(@enabledAtRuntime, $attribute); + } + } + + GenerateHeaderRuntimeEnablerDeclarations(@enabledAtRuntime); + GenerateHeaderNamedAndIndexedPropertyAccessors($dataNode); + GenerateHeaderCustomCall($dataNode); + GenerateHeaderCustomInternalFieldIndices($dataNode); + + 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); +END + } + push(@headerContent, <<END); private: @@ -298,6 +354,172 @@ END push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString; } +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 (); +} + +sub GetHeaderClassInclude +{ + my $className = shift; + if ($className =~ /SVGPathSeg/) { + $className =~ s/Abs|Rel//; + } + return "" if (AvoidInclusionOfType($className)); + return "#include \"SVGAnimatedTemplate.h\"\n" if ($codeGenerator->IsSVGAnimatedType($className)); + return "#include \"${className}.h\"\n"; +} + +sub GenerateHeaderCustomInternalFieldIndices +{ + my $dataNode = shift; + my @customInternalFields = GetInternalFields($dataNode); + my $customFieldCounter = 0; + foreach my $customInternalField (@customInternalFields) { + push(@headerContent, <<END); + static const int ${customInternalField} = v8DefaultWrapperInternalFieldCount + ${customFieldCounter}; +END + $customFieldCounter++; + } + push(@headerContent, <<END); + static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + ${customFieldCounter}; +END +} + +sub GenerateHeaderRuntimeEnablerDeclarations +{ + my @enabledAtRuntime = @_; + + foreach my $runtime_attr (@enabledAtRuntime) { + my $enabledAtRuntimeConditionalString = GenerateConditionalString($runtime_attr->signature); + my $enabler = $codeGenerator->WK_ucfirst($runtime_attr->signature->name); + if ($enabledAtRuntimeConditionalString) { + push(@headerContent, "\n#if ${enabledAtRuntimeConditionalString}\n"); + } + push(@headerContent, <<END); + static bool ${enabler}Enabled(); +END + if ($enabledAtRuntimeConditionalString) { + push(@headerContent, "#endif\n"); + } + } +} + +my %indexerSpecialCases = ( + "Storage" => 1, + "HTMLAppletElement" => 1, + "HTMLDocument" => 1, + "HTMLEmbedElement" => 1, + "HTMLObjectElement" => 1 +); + +sub GenerateHeaderNamedAndIndexedPropertyAccessors +{ + my $dataNode = shift; + my $interfaceName = $dataNode->name; + my $hasCustomIndexedGetter = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}; + my $hasCustomIndexedSetter = $dataNode->extendedAttributes->{"HasCustomIndexSetter"} && !$dataNode->extendedAttributes->{"HasNumericIndexGetter"}; + my $hasCustomNamedGetter = $dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}; + my $hasCustomNamedSetter = $dataNode->extendedAttributes->{"DelegatingPutFunction"}; + my $hasCustomDeleters = $dataNode->extendedAttributes->{"CustomDeleteProperty"}; + my $hasCustomEnumerator = $dataNode->extendedAttributes->{"CustomGetPropertyNames"}; + if ($interfaceName eq "HTMLOptionsCollection") { + $interfaceName = "HTMLCollection"; + $hasCustomIndexedGetter = 1; + $hasCustomNamedGetter = 1; + } + if ($interfaceName eq "DOMWindow") { + $hasCustomDeleterr = 0; + $hasEnumerator = 0; + } + if ($interfaceName eq "HTMLSelectElement") { + $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); +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); +END + } + if ($hasCustomDeleters) { + push(@headerContent, <<END); + 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); +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); +END + } + if ($hasCustomDeleters || $interfaceName eq "HTMLDocument") { + push(@headerContent, <<END); + 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); +END + } +} + +sub GenerateHeaderCustomCall +{ + my $dataNode = shift; + + if ($dataNode->extendedAttributes->{"CustomCall"}) { + 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"); + } + 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"); + } +} sub GenerateSetDOMException { @@ -323,48 +545,6 @@ sub IsNodeSubType return 0; } -sub GetHiddenDependencyIndex -{ - my $dataNode = shift; - my $attribute = shift; - my $name = $dataNode->name; - return "V8Custom::kNodeEventListenerCacheIndex" if IsNodeSubType($dataNode); - return "V8Custom::kSVGElementInstanceEventListenerCacheIndex" if $name eq "SVGElementInstance"; - return "V8Custom::kAbstractWorkerRequestCacheIndex" if $name eq "AbstractWorker"; - return "V8Custom::kWorkerRequestCacheIndex" if $name eq "Worker"; - return "V8Custom::kDedicatedWorkerContextRequestCacheIndex" if $name eq "DedicatedWorkerContext"; - return "V8Custom::kWorkerContextRequestCacheIndex" if $name eq "WorkerContext"; - return "V8Custom::kWorkerContextRequestCacheIndex" if $name eq "SharedWorkerContext"; - return "V8Custom::kMessagePortRequestCacheIndex" if $name eq "MessagePort"; - return "V8Custom::kWebSocketCacheIndex" if $name eq "WebSocket"; - return "V8Custom::kXMLHttpRequestCacheIndex" if $name eq "XMLHttpRequest"; - return "V8Custom::kXMLHttpRequestCacheIndex" if $name eq "XMLHttpRequestUpload"; - return "V8Custom::kDOMApplicationCacheCacheIndex" if $name eq "DOMApplicationCache"; - return "V8Custom::kNotificationRequestCacheIndex" if $name eq "Notification"; - return "V8Custom::kDOMWindowEventListenerCacheIndex" if $name eq "DOMWindow"; - die "Unexpected name " . $name . " when generating " . $attribute; -} - -sub HolderToNative -{ - my $dataNode = shift; - my $implClassName = shift; - my $classIndex = shift; - my $holder = shift || "holder"; # optional param - - if (IsNodeSubType($dataNode)) { - push(@implContentDecls, <<END); - $implClassName* imp = v8DOMWrapperToNode<$implClassName>($holder); -END - - } else { - push(@implContentDecls, <<END); - $implClassName* imp = v8DOMWrapperTo<$implClassName>(V8ClassIndex::$classIndex, $holder); -END - - } -} - sub GenerateDomainSafeFunctionGetter { my $function = shift; @@ -382,8 +562,6 @@ sub GenerateDomainSafeFunctionGetter my $newTemplateString = GenerateNewFunctionTemplate($function, $dataNode, $signature); - $implIncludes{"V8Proxy.h"} = 1; - push(@implContentDecls, <<END); static v8::Handle<v8::Value> ${funcName}AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS(\"DOM.$implClassName.$funcName._get\"); @@ -393,15 +571,10 @@ sub GenerateDomainSafeFunctionGetter if (holder.IsEmpty()) { // can only reach here by 'object.__proto__.func', and it should passed // domain security check already - return private_template->GetFunction(); } -END - - HolderToNative($dataNode, $implClassName, $classIndex); - - push(@implContentDecls, <<END); - if (!V8Proxy::canAccessFrame(imp->frame(), false)) { + ${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(); @@ -429,17 +602,15 @@ END if ($classIndex eq "DOMWINDOW") { push(@implContentDecls, <<END); - DOMWindow* window = v8DOMWrapperTo<DOMWindow>(V8ClassIndex::DOMWINDOW, info.Holder()); // 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, window); + return V8DOMWrapper::getConstructor(type, V8DOMWindow::toNative(info.Holder())); END } elsif ($classIndex eq "DEDICATEDWORKERCONTEXT" or $classIndex eq "WORKERCONTEXT" or $classIndex eq "SHAREDWORKERCONTEXT") { $implIncludes{"WorkerContextExecutionProxy.h"} = 1; push(@implContentDecls, <<END); - WorkerContext* workerContext = v8DOMWrapperTo<WorkerContext>(V8ClassIndex::WORKERCONTEXT, info.Holder()); - return V8DOMWrapper::getConstructor(type, workerContext); + return V8DOMWrapper::getConstructor(type, V8WorkerContext::toNative(info.Holder())); END } else { push(@implContentDecls, " return v8::Handle<v8::Value>();"); @@ -463,7 +634,6 @@ sub GenerateNormalAttrGetter my $attrExt = $attribute->signature->extendedAttributes; my $attrName = $attribute->signature->name; - $implIncludes{"V8Proxy.h"} = 1; my $attrType = GetTypeFromSignature($attribute->signature); my $attrIsPodType = IsPodType($attrType); @@ -505,7 +675,7 @@ END if ($isPodType) { push(@implContentDecls, <<END); - V8SVGPODTypeWrapper<$implClassName>* imp_wrapper = v8DOMWrapperTo<V8SVGPODTypeWrapper<$implClassName> >(V8ClassIndex::$classIndex, info.Holder()); + V8SVGPODTypeWrapper<$implClassName>* imp_wrapper = V8SVGPODTypeWrapper<$implClassName>::toNative(info.Holder()); $implClassName imp_instance = *imp_wrapper; END if ($getterStringUsesImp) { @@ -526,7 +696,9 @@ END if (holder.IsEmpty()) return v8::Handle<v8::Value>(); END } - HolderToNative($dataNode, $implClassName, $classIndex, "info"); + push(@implContentDecls, <<END); + ${implClassName}* imp = V8${implClassName}::toNative(holder); +END } else { my $reflect = $attribute->signature->extendedAttributes->{"Reflect"}; if ($getterStringUsesImp && $reflect && IsNodeSubType($dataNode) && $codeGenerator->IsStringType($attrType)) { @@ -539,18 +711,16 @@ END return; # Skip the rest of the function! } - push(@implContentDecls, <<END); - v8::Handle<v8::Object> holder = info.Holder(); + ${implClassName}* imp = V8${implClassName}::toNative(info.Holder()); END - HolderToNative($dataNode, $implClassName, $classIndex, "info"); } # Generate security checks if necessary if ($attribute->signature->extendedAttributes->{"CheckNodeSecurity"}) { - push(@implContentDecls, " if (!V8Proxy::checkNodeSecurity(imp->$attrName())) return v8::Handle<v8::Value>();\n\n"); + push(@implContentDecls, " if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->$attrName())) return v8::Handle<v8::Value>();\n\n"); } elsif ($attribute->signature->extendedAttributes->{"CheckFrameSecurity"}) { - push(@implContentDecls, " if (!V8Proxy::checkNodeSecurity(imp->contentDocument())) return v8::Handle<v8::Value>();\n\n"); + push(@implContentDecls, " if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->contentDocument())) return v8::Handle<v8::Value>();\n\n"); } my $useExceptions = 1 if @{$attribute->getterExceptions} and !($isPodType); @@ -670,8 +840,6 @@ sub GenerateReplaceableAttrSetter { my $implClassName = shift; - $implIncludes{"V8Proxy.h"} = 1; - push(@implContentDecls, " static void ${attrName}AttrSetter(v8::Local<v8::String> name," . " v8::Local<v8::Value> value, const v8::AccessorInfo& info) {\n"); @@ -695,8 +863,6 @@ sub GenerateNormalAttrSetter my $attrExt = $attribute->signature->extendedAttributes; - $implIncludes{"V8Proxy.h"} = 1; - push(@implContentDecls, " static void ${attrName}AttrSetter(v8::Local<v8::String> name," . " v8::Local<v8::Value> value, const v8::AccessorInfo& info) {\n"); @@ -708,7 +874,7 @@ sub GenerateNormalAttrSetter if ($isPodType) { $implClassName = GetNativeType($implClassName); $implIncludes{"V8SVGPODTypeWrapper.h"} = 1; - push(@implContentDecls, " V8SVGPODTypeWrapper<$implClassName>* wrapper = v8DOMWrapperTo<V8SVGPODTypeWrapper<$implClassName> >(V8ClassIndex::$classIndex, info.Holder());\n"); + 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"); @@ -724,7 +890,9 @@ END if (holder.IsEmpty()) return; END } - HolderToNative($dataNode, $implClassName, $classIndex, "info"); + push(@implContentDecls, <<END); + ${implClassName}* imp = V8${implClassName}::toNative(holder); +END } else { my $attrType = GetTypeFromSignature($attribute->signature); my $reflect = $attribute->signature->extendedAttributes->{"Reflect"}; @@ -741,9 +909,8 @@ END } push(@implContentDecls, <<END); - v8::Handle<v8::Object> holder = info.Holder(); + ${implClassName}* imp = V8${implClassName}::toNative(info.Holder()); END - HolderToNative($dataNode, $implClassName, $classIndex, "info"); } my $nativeType = GetNativeTypeFromSignature($attribute->signature, 0); @@ -790,8 +957,7 @@ END } elsif ($attribute->signature->type eq "EventListener") { $implIncludes{"V8AbstractEventListener.h"} = 1; $implIncludes{"V8CustomBinding.h"} = 1; - $cacheIndex = GetHiddenDependencyIndex($dataNode, $attrName); - push(@implContentDecls, " transferHiddenDependency(holder, imp->$attrName(), value, $cacheIndex);\n"); + push(@implContentDecls, " transferHiddenDependency(info.Holder(), imp->$attrName(), value, V8${interfaceName}::cacheIndex);\n"); push(@implContentDecls, " imp->set$implSetterFunctionName(V8DOMWrapper::getEventListener(imp, value, true, ListenerFindOrCreate)"); } else { push(@implContentDecls, " imp->set$implSetterFunctionName($result"); @@ -838,12 +1004,7 @@ sub GetFunctionTemplateCallbackName $function->signature->extendedAttributes->{"V8Custom"}) { die "Custom and V8Custom should be mutually exclusive!" } - my $customFunc = $function->signature->extendedAttributes->{"Custom"} || - $function->signature->extendedAttributes->{"V8Custom"}; - if ($customFunc eq 1) { - $customFunc = $interfaceName . $codeGenerator->WK_ucfirst($name); - } - return "V8Custom::v8${customFunc}Callback"; + return "V8${interfaceName}::${name}Callback"; } else { return "${interfaceName}Internal::${name}Callback"; } @@ -882,14 +1043,13 @@ sub GenerateFunctionCallback if (IsPodType($implClassName)) { my $nativeClassName = GetNativeType($implClassName); - push(@implContentDecls, " V8SVGPODTypeWrapper<$nativeClassName>* imp_wrapper = v8DOMWrapperTo<V8SVGPODTypeWrapper<$nativeClassName> >(V8ClassIndex::$classIndex, args.Holder());\n"); + 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"); } else { push(@implContentDecls, <<END); - v8::Handle<v8::Object> holder = args.Holder(); + ${implClassName}* imp = V8${implClassName}::toNative(args.Holder()); END - HolderToNative($dataNode, $implClassName, $classIndex); } # Check domain security if needed @@ -898,7 +1058,7 @@ END && !$function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) { # We have not find real use cases yet. push(@implContentDecls, -" if (!V8Proxy::canAccessFrame(imp->frame(), true)) {\n". +" if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true)) {\n". " return v8::Handle<v8::Value>();\n" . " }\n"); } @@ -930,7 +1090,7 @@ END } if ($function->signature->extendedAttributes->{"SVGCheckSecurityDocument"}) { push(@implContentDecls, -" if (!V8Proxy::checkNodeSecurity(imp->getSVGDocument(ec)))\n" . +" if (!V8BindingSecurity::checkNodeSecurity(V8BindingState::Only(), imp->getSVGDocument(ec)))\n" . " return v8::Handle<v8::Value>();\n"); } @@ -1040,7 +1200,7 @@ sub GenerateSingleBatchedAttribute ""; if ($customAccessor eq 1) { # use the naming convension, interface + (capitalize) attr name - $customAccessor = $interfaceName . $codeGenerator->WK_ucfirst($attrName); + $customAccessor = $interfaceName . "::" . $attrName; } my $getter; @@ -1065,7 +1225,7 @@ sub GenerateSingleBatchedAttribute $constructorType =~ s/Constructor$//; my $constructorIndex = uc($constructorType); if ($customAccessor) { - $getter = "V8Custom::v8${customAccessor}AccessorGetter"; + $getter = "V8${customAccessor}AccessorGetter"; } else { $data = "V8ClassIndex::${constructorIndex}"; $getter = "${interfaceName}Internal::${interfaceName}ConstructorGetter"; @@ -1081,12 +1241,12 @@ sub GenerateSingleBatchedAttribute # Custom Setter if ($attrExt->{"CustomSetter"} || $attrExt->{"V8CustomSetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) { $hasCustomSetter = 1; - $setter = "V8Custom::v8${customAccessor}AccessorSetter"; + $setter = "V8${customAccessor}AccessorSetter"; } # Custom Getter - if ($attrExt->{"CustomGetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) { - $getter = "V8Custom::v8${customAccessor}AccessorGetter"; + if ($attrExt->{"CustomGetter"} || $attrExt->{"V8CustomGetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) { + $getter = "V8${customAccessor}AccessorGetter"; } } @@ -1127,6 +1287,172 @@ sub GenerateSingleBatchedAttribute END } +sub GenerateImplementationIndexer +{ + my $dataNode = shift; + my $indexer = shift; + my $interfaceName = $dataNode->name; + + # FIXME: Figure out what HasNumericIndexGetter is really supposed to do. Right now, it's only set on WebGL-related files. + my $hasCustomSetter = $dataNode->extendedAttributes->{"HasCustomIndexSetter"} && !$dataNode->extendedAttributes->{"HasNumericIndexGetter"}; + my $hasGetter = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}; + + # FIXME: Find a way to not have to special-case HTMLOptionsCollection. + if ($interfaceName eq "HTMLOptionsCollection") { + $hasGetter = 1; + } + # FIXME: If the parent interface of $dataNode already has + # HasIndexGetter, we don't need to handle the getter here. + if ($interfaceName eq "WebKitCSSTransformValue") { + $hasGetter = 0; + } + + # FIXME: Investigate and remove this nastinesss. In V8, named property handling and indexer handling are apparently decoupled, + # which means that object[X] where X is a number doesn't reach named property indexer. So we need to provide + # simplistic, mirrored indexer handling in addition to named property handling. + my $isSpecialCase = exists $indexerSpecialCases{$interfaceName}; + if ($isSpecialCase) { + $hasGetter = 1; + if ($dataNode->extendedAttributes->{"DelegatingPutFunction"}) { + $hasCustomSetter = 1; + } + } + + if (!$hasGetter) { + return; + } + + $implIncludes{"V8Collection.h"} = 1; + + my $indexerType = $indexer ? $indexer->type : 0; + + # FIXME: Remove this once toV8 helper methods are implemented (see https://bugs.webkit.org/show_bug.cgi?id=32563). + if ($interfaceName eq "WebKitCSSKeyframesRule") { + $indexerType = "WebKitCSSKeyframeRule"; + } + + if ($indexerType && !$hasCustomSetter) { + if ($indexerType eq "DOMString") { + my $conversion = $indexer->extendedAttributes->{"ConvertNullStringTo"}; + if ($conversion && $conversion eq "Null") { + push(@implContent, <<END); + setCollectionStringOrNullIndexedGetter<${interfaceName}>(desc); +END + } else { + push(@implContent, <<END); + setCollectionStringIndexedGetter<${interfaceName}>(desc); +END + } + } else { + my $indexerClassIndex = uc($indexerType); + push(@implContent, <<END); + setCollectionIndexedGetter<${interfaceName}, ${indexerType}>(desc, V8ClassIndex::${indexerClassIndex}); +END + } + + return; + } + + my $hasDeleter = $dataNode->extendedAttributes->{"CustomDeleteProperty"}; + my $hasEnumerator = !$isSpecialCase && IsNodeSubType($dataNode); + my $setOn = "Instance"; + + # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow + # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to + # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set + # on the object. + if ($interfaceName eq "DOMWindow") { + $setOn = "Prototype"; + $hasDeleter = 0; + } + + 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, ");\n"); +} + +sub GenerateImplementationNamedPropertyGetter +{ + my $dataNode = shift; + my $namedPropertyGetter = shift; + my $interfaceName = $dataNode->name; + my $hasCustomGetter = $dataNode->extendedAttributes->{"HasOverridingNameGetter"} || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}; + + # FIXME: Remove hard-coded HTMLOptionsCollection reference by changing HTMLOptionsCollection to not inherit + # from HTMLCollection per W3C spec (http://www.w3.org/TR/2003/REC-DOM-Level-2-HTML-20030109/html.html#HTMLOptionsCollection). + if ($interfaceName eq "HTMLOptionsCollection") { + $interfaceName = "HTMLCollection"; + $hasCustomGetter = 1; + } + + my $hasGetter = $dataNode->extendedAttributes->{"HasNameGetter"} || $hasCustomGetter || $namedPropertyGetter; + if (!$hasGetter) { + return; + } + + 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}); +END + return; + } + + my $hasSetter = $dataNode->extendedAttributes->{"DelegatingPutFunction"}; + # FIXME: Try to remove hard-coded HTMLDocument reference by aligning handling of document.all with JSC bindings. + my $hasDeleter = $dataNode->extendedAttributes->{"CustomDeleteProperty"} || $interfaceName eq "HTMLDocument"; + my $hasEnumerator = $dataNode->extendedAttributes->{"CustomGetPropertyNames"}; + my $setOn = "Instance"; + + # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on DOMWindow + # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to + # get implementation straight out of the DOMWindow prototype regardless of what prototype is actually set + # on the object. + if ($interfaceName eq "DOMWindow") { + $setOn = "Prototype"; + $hasDeleter = 0; + $hasEnumerator = 0; + } + + 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, "); + push(@implContent, $hasEnumerator ? "V8${interfaceName}::namedPropertyEnumerator" : "0"); + push(@implContent, ");\n"); +} + +sub GenerateImplementationCustomCall +{ + my $dataNode = shift; + my $interfaceName = $dataNode->name; + my $hasCustomCall = $dataNode->extendedAttributes->{"CustomCall"}; + + # FIXME: Remove hard-coded HTMLOptionsCollection reference. + if ($interfaceName eq "HTMLOptionsCollection") { + $interfaceName = "HTMLCollection"; + $hasCustomCall = 1; + } + + if ($hasCustomCall) { + push(@implContent, " desc->InstanceTemplate()->SetCallAsFunctionHandler(V8${interfaceName}::callAsFunctionCallback);\n"); + } +} + +sub GenerateImplementationMasqueradesAsUndefined +{ + my $dataNode = shift; + if ($dataNode->extendedAttributes->{"MasqueradesAsUndefined"}) + { + push(@implContent, " desc->InstanceTemplate()->MarkAsUndetectable();\n"); + } +} + sub GenerateImplementation { my $object = shift; @@ -1145,7 +1471,8 @@ sub GenerateImplementation push(@implFixedHeader, "#include \"config.h\"\n" . "#include \"V8Proxy.h\"\n" . - "#include \"V8Binding.h\"\n\n" . + "#include \"V8Binding.h\"\n" . + "#include \"V8BindingState.h\"\n\n" . "#undef LOG\n\n"); push(@implFixedHeader, "\n#if ${conditionalString}\n\n") if $conditionalString; @@ -1157,14 +1484,12 @@ sub GenerateImplementation $implIncludes{"${className}.h"} = 1; AddIncludesForType($interfaceName); - $implIncludes{"V8Proxy.h"} = 1; push(@implContentDecls, "namespace WebCore {\n"); push(@implContentDecls, "namespace ${interfaceName}Internal {\n\n"); push(@implContentDecls, "template <typename T> void V8_USE(T) { }\n\n"); my $hasConstructors = 0; - # Generate property accessors for attributes. for ($index = 0; $index < @{$dataNode->attributes}; $index++) { $attribute = @{$dataNode->attributes}[$index]; @@ -1173,7 +1498,8 @@ sub GenerateImplementation # Generate special code for the constructor attributes. if ($attrType =~ /Constructor$/) { - if ($attribute->signature->extendedAttributes->{"CustomGetter"}) { + if ($attribute->signature->extendedAttributes->{"CustomGetter"} || + $attribute->signature->extendedAttributes->{"V8CustomGetter"}) { $implIncludes{"V8CustomBinding.h"} = 1; } else { $hasConstructors = 1; @@ -1195,7 +1521,8 @@ sub GenerateImplementation } # Generate the accessor. - if ($attribute->signature->extendedAttributes->{"CustomGetter"}) { + if ($attribute->signature->extendedAttributes->{"CustomGetter"} || + $attribute->signature->extendedAttributes->{"V8CustomGetter"}) { $implIncludes{"V8CustomBinding.h"} = 1; } else { GenerateNormalAttrGetter($attribute, $dataNode, $classIndex, $implClassName, $interfaceName); @@ -1214,7 +1541,9 @@ sub GenerateImplementation if ($hasConstructors) { GenerateConstructorGetter($implClassName, $classIndex); } - + + my $indexer; + my $namedPropertyGetter; # Generate methods for functions. foreach my $function (@{$dataNode->functions}) { # hack for addEventListener/RemoveEventListener @@ -1225,6 +1554,14 @@ sub GenerateImplementation GenerateFunctionCallback($function, $dataNode, $classIndex, $implClassName); } + if ($function->signature->name eq "item") { + $indexer = $function->signature; + } + + if ($function->signature->name eq "namedItem") { + $namedPropertyGetter = $function->signature; + } + # If the function does not need domain security check, we need to # generate an access getter that returns different function objects # for different calling context. @@ -1243,6 +1580,7 @@ sub GenerateImplementation my @enabledAtRuntime; my @normal; foreach my $attribute (@$attributes) { + if ($interfaceName eq "DOMWindow" && $attribute->signature->extendedAttributes->{"V8DisallowShadowing"}) { push(@disallowsShadowing, $attribute); } elsif ($attribute->signature->extendedAttributes->{"EnabledAtRuntime"}) { @@ -1321,9 +1659,20 @@ END push(@implContentDecls, "} // namespace ${interfaceName}Internal\n\n"); + # 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) + { + INC_STATS("DOM.${interfaceName}.Contructor"); + return V8Proxy::constructDOMObject<V8ClassIndex::${classIndex}, $interfaceName>(args); + } +END + } + my $access_check = ""; if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && !($interfaceName eq "DOMWindow")) { - $access_check = "instance->SetAccessCheckCallbacks(V8Custom::v8${interfaceName}NamedSecurityCheck, V8Custom::v8${interfaceName}IndexedSecurityCheck, v8::Integer::New(V8ClassIndex::ToInt(V8ClassIndex::${classIndex})));"; + $access_check = "instance->SetAccessCheckCallbacks(V8${interfaceName}::namedSecurityCheck, V8${interfaceName}::indexedSecurityCheck, v8::Integer::New(V8ClassIndex::ToInt(V8ClassIndex::${classIndex})));"; } # For the DOMWindow interface, generate the shadow object template @@ -1335,6 +1684,10 @@ static v8::Persistent<v8::ObjectTemplate> ConfigureShadowObjectTemplate(v8::Pers v8::Handle<v8::ObjectTemplate>(), shadow_attrs, sizeof(shadow_attrs)/sizeof(*shadow_attrs)); + + // Install a security handler with V8. + templ->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::Integer::New(V8ClassIndex::DOMWINDOW)); + templ->SetInternalFieldCount(V8DOMWindow::internalFieldCount); return templ; } END @@ -1349,20 +1702,13 @@ END $parentClassIndex = uc($codeGenerator->StripModule($parent)); last; } - - # find the field count - my $fieldCount = "V8Custom::kDefaultWrapperInternalFieldCount"; - if (IsNodeSubType($dataNode)) { - $fieldCount = "V8Custom::kNodeMinimumInternalFieldCount"; - } # 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}\", - V8ClassIndex::$parentClassIndex, $fieldCount, + V8ClassIndex::$parentClassIndex, V8${interfaceName}::internalFieldCount, END - # Set up our attributes if we have them if ($has_attributes) { push(@implContent, <<END); @@ -1384,6 +1730,12 @@ END END } + if ($dataNode->extendedAttributes->{"CustomConstructor"} || $dataNode->extendedAttributes->{"CanBeConstructed"}) { + push(@implContent, <<END); + 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(); @@ -1395,10 +1747,10 @@ END # Setup the enable-at-runtime attrs if we have them foreach my $runtime_attr (@enabledAtRuntime) { - $enable_function = $interfaceName . $codeGenerator->WK_ucfirst($runtime_attr->signature->name); + $enable_function = $interfaceName . "::" . $codeGenerator->WK_ucfirst($runtime_attr->signature->name); my $conditionalString = GenerateConditionalString($runtime_attr->signature); push(@implContent, "\n#if ${conditionalString}\n") if $conditionalString; - push(@implContent, " if (V8Custom::v8${enable_function}Enabled()) {\n"); + push(@implContent, " if (V8${enable_function}Enabled()) {\n"); push(@implContent, " static const BatchedAttribute attrData =\\\n"); GenerateSingleBatchedAttribute($interfaceName, $runtime_attr, ";", " "); push(@implContent, <<END); @@ -1408,6 +1760,11 @@ END push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString; } + GenerateImplementationIndexer($dataNode, $indexer); + GenerateImplementationNamedPropertyGetter($dataNode, $namedPropertyGetter); + GenerateImplementationCustomCall($dataNode); + GenerateImplementationMasqueradesAsUndefined($dataNode); + # Define our functions with Set() or SetAccessor() $total_functions = 0; foreach my $function (@{$dataNode->functions}) { @@ -1433,8 +1790,8 @@ END my $conditional = ""; if ($attrExt->{"EnabledAtRuntime"}) { # Only call Set()/SetAccessor() if this method should be enabled - $enable_function = $interfaceName . $codeGenerator->WK_ucfirst($function->signature->name); - $conditional = "if (V8Custom::v8${enable_function}Enabled())\n"; + $enable_function = $interfaceName . "::" . $codeGenerator->WK_ucfirst($function->signature->name); + $conditional = "if (V8${enable_function}Enabled())\n"; } if ($attrExt->{"DoNotCheckDomainSecurity"} && @@ -1494,7 +1851,7 @@ END } push(@implContent, <<END); - ${conditional}createCallback($template, "$name", $callback, ${signature}$property_attributes); + ${conditional}$template->Set(v8::String::New("$name"), v8::FunctionTemplate::New($callback, v8::Handle<v8::Value>(), ${signature})$property_attributes); END $num_callbacks++; } @@ -1506,8 +1863,36 @@ END batchConfigureConstants(desc, proto, ${interfaceName}_consts, sizeof(${interfaceName}_consts)/sizeof(*${interfaceName}_consts)); END } + + # Special cases + 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); +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)); +END + } + $toNativeReturnType = GetReturnTypeForToNative($interfaceName); push(@implContent, <<END); + + // Custom toString template + desc->Set(getToStringName(), getToStringTemplate()); return desc; } @@ -1521,6 +1906,10 @@ v8::Persistent<v8::FunctionTemplate> ${className}::GetTemplate() { return ${className}_cache_; } +${toNativeReturnType}* ${className}::toNative(v8::Handle<v8::Object> object) { + return reinterpret_cast<${toNativeReturnType}*>(object->GetPointerFromInternalField(v8DOMWrapperObjectIndex)); +} + bool ${className}::HasInstance(v8::Handle<v8::Value> value) { return GetRawTemplate()->HasInstance(value); } @@ -1547,6 +1936,15 @@ END push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString; } +sub GetReturnTypeForToNative +{ + my $type = shift; + return "FloatRect" if $type eq "SVGRect"; + return "FloatPoint" if $type eq "SVGPoint"; + return "TransformationMatrix" if $type eq "SVGMatrix"; + return "float" if $type eq "SVGNumber"; + return $type; +} sub GenerateFunctionCallString() { @@ -1757,101 +2155,20 @@ sub GetNativeTypeFromSignature sub IsRefPtrType { my $type = shift; - return 1 if $type eq "Attr"; - return 1 if $type eq "CanvasBooleanArray"; - return 1 if $type eq "CanvasGradient"; - return 1 if $type eq "CanvasObject"; - return 1 if $type eq "ClientRect"; - return 1 if $type eq "ClientRectList"; - return 1 if $type eq "CDATASection"; - return 1 if $type eq "Comment"; - return 1 if $type eq "CSSRule"; - return 1 if $type eq "CSSStyleRule"; - return 1 if $type eq "CSSCharsetRule"; - return 1 if $type eq "CSSImportRule"; - return 1 if $type eq "CSSMediaRule"; - return 1 if $type eq "CSSFontFaceRule"; - return 1 if $type eq "CSSPageRule"; - return 1 if $type eq "CSSPrimitiveValue"; - return 1 if $type eq "CSSStyleSheet"; - return 1 if $type eq "CSSStyleDeclaration"; - return 1 if $type eq "CSSValue"; - return 1 if $type eq "CSSRuleList"; - return 1 if $type eq "Database"; - return 1 if $type eq "Document"; - return 1 if $type eq "DocumentFragment"; - return 1 if $type eq "DocumentType"; - return 1 if $type eq "Element"; - return 1 if $type eq "EntityReference"; - return 1 if $type eq "Event"; - return 1 if $type eq "EventListener"; - return 1 if $type eq "FileList"; - return 1 if $type eq "HTMLCollection"; - return 1 if $type eq "HTMLAllCollection"; - return 1 if $type eq "HTMLDocument"; - return 1 if $type eq "HTMLElement"; - return 1 if $type eq "HTMLOptionsCollection"; - return 1 if $type eq "ImageData"; - return 1 if $type eq "Media"; - return 1 if $type eq "MediaError"; - return 1 if $type eq "MimeType"; - return 1 if $type eq "Node"; - return 1 if $type eq "NodeList"; - return 1 if $type eq "NodeFilter"; - return 1 if $type eq "NodeIterator"; - return 1 if $type eq "NSResolver"; - return 1 if $type eq "Plugin"; - return 1 if $type eq "ProcessingInstruction"; - return 1 if $type eq "Range"; - return 1 if $type eq "RGBColor"; - return 1 if $type eq "Text"; - return 1 if $type eq "TextMetrics"; - return 1 if $type eq "TimeRanges"; - return 1 if $type eq "TreeWalker"; - return 1 if $type eq "WebGLActiveInfo"; - return 1 if $type eq "WebGLArray"; - return 1 if $type eq "WebGLArrayBuffer"; - return 1 if $type eq "WebGLByteArray"; - return 1 if $type eq "WebGLBuffer"; - return 1 if $type eq "WebGLFloatArray"; - return 1 if $type eq "WebGLFramebuffer"; - return 1 if $type eq "WebGLIntArray"; - return 1 if $type eq "WebGLProgram"; - return 1 if $type eq "WebGLRenderbuffer"; - return 1 if $type eq "WebGLShader"; - return 1 if $type eq "WebGLShortArray"; - return 1 if $type eq "WebGLTexture"; - return 1 if $type eq "WebGLUniformLocation"; - return 1 if $type eq "WebGLUnsignedByteArray"; - return 1 if $type eq "WebGLUnsignedIntArray"; - return 1 if $type eq "WebGLUnsignedShortArray"; - return 1 if $type eq "WebKitCSSMatrix"; - return 1 if $type eq "WebKitPoint"; - return 1 if $type eq "XPathExpression"; - return 1 if $type eq "XPathNSResolver"; - return 1 if $type eq "XPathResult"; - - return 1 if $type eq "SVGAngle"; - return 1 if $type eq "SVGElementInstance"; - return 1 if $type eq "SVGElementInstanceList"; - return 1 if $type =~ /^SVGPathSeg/; - - return 1 if $type =~ /^SVGAnimated/; - - return 0; -} -sub IsVideoClassName -{ - my $class = shift; - return 1 if $class eq "V8HTMLAudioElement"; - return 1 if $class eq "V8HTMLMediaElement"; - return 1 if $class eq "V8HTMLSourceElement"; - return 1 if $class eq "V8HTMLVideoElement"; - return 1 if $class eq "V8MediaError"; - return 1 if $class eq "V8TimeRanges"; - - return 0; + return 0 if $type eq "boolean"; + return 0 if $type eq "float"; + return 0 if $type eq "int"; + return 0 if $type eq "Date"; + return 0 if $type eq "DOMString"; + return 0 if $type eq "double"; + return 0 if $type eq "short"; + return 0 if $type eq "long"; + return 0 if $type eq "unsigned"; + return 0 if $type eq "unsigned long"; + return 0 if $type eq "unsigned short"; + + return 1; } sub IsWorkerClassName @@ -1879,6 +2196,7 @@ sub GetNativeType return "int" if $type eq "short" or $type eq "unsigned short"; return "unsigned" if $type eq "unsigned long"; return "int" if $type eq "long"; + return "long long" if $type eq "long long"; return "unsigned long long" if $type eq "unsigned long long"; return "bool" if $type eq "boolean"; return "String" if $type eq "DOMString"; @@ -1888,11 +2206,14 @@ sub GetNativeType return "TransformationMatrix" if $type eq "SVGMatrix"; return "SVGTransform" if $type eq "SVGTransform"; return "SVGLength" if $type eq "SVGLength"; + return "SVGAngle" if $type eq "SVGAngle"; return "double" if $type eq "SVGNumber"; + return "SVGPreserveAspectRatio" if $type eq "SVGPreserveAspectRatio"; return "SVGPaint::SVGPaintType" if $type eq "SVGPaintType"; return "DOMTimeStamp" if $type eq "DOMTimeStamp"; return "unsigned" if $type eq "unsigned int"; return "Node*" if $type eq "EventTarget" and $isParameter; + return "double" if $type eq "Date"; return "String" if $type eq "DOMUserData"; # FIXME: Temporary hack? @@ -1914,6 +2235,8 @@ my %typeCanFailConversion = ( "WebGLArray" => 0, "WebGLBuffer" => 0, "WebGLByteArray" => 0, + "WebGLUnsignedByteArray" => 0, + "WebGLContextAttributes" => 0, "WebGLFloatArray" => 0, "WebGLFramebuffer" => 0, "CanvasGradient" => 0, @@ -1946,7 +2269,7 @@ my %typeCanFailConversion = ( "Range" => 0, "SQLResultSet" => 0, "Storage" => 0, - "SVGAngle" => 0, + "SVGAngle" => 1, "SVGElement" => 0, "SVGLength" => 1, "SVGMatrix" => 1, @@ -1954,6 +2277,7 @@ my %typeCanFailConversion = ( "SVGPaintType" => 0, "SVGPathSeg" => 0, "SVGPoint" => 1, + "SVGPreserveAspectRatio" => 1, "SVGRect" => 1, "SVGTransform" => 1, "TouchList" => 0, @@ -1969,6 +2293,8 @@ my %typeCanFailConversion = ( "long" => 0, "unsigned long" => 0, "unsigned short" => 0, + "long long" => 0, + "unsigned long long" => 0 ); @@ -1987,9 +2313,11 @@ sub BasicTypeCanFailConversion my $signature = shift; my $type = GetTypeFromSignature($signature); + return 1 if $type eq "SVGAngle"; return 1 if $type eq "SVGLength"; return 1 if $type eq "SVGMatrix"; return 1 if $type eq "SVGPoint"; + return 1 if $type eq "SVGPreserveAspectRatio"; return 1 if $type eq "SVGRect"; return 1 if $type eq "SVGTransform"; return 0; @@ -2023,8 +2351,10 @@ sub JSValueToNative return "$value->NumberValue()" if $type eq "SVGNumber"; return "toInt32($value${maybeOkParam})" if $type eq "unsigned long" or $type eq "unsigned short" or $type eq "long"; + return "toInt64($value)" if $type eq "unsigned long long" or $type eq "long long"; return "static_cast<Range::CompareHow>($value->Int32Value())" if $type eq "CompareHow"; return "static_cast<SVGPaint::SVGPaintType>($value->ToInt32()->Int32Value())" if $type eq "SVGPaintType"; + return "toWebCoreDate($value)" if $type eq "Date"; if ($type eq "DOMString" or $type eq "DOMUserData") { return $value; @@ -2048,12 +2378,11 @@ sub JSValueToNative } # Default, assume autogenerated type conversion routines - $implIncludes{"V8Proxy.h"} = 1; if ($type eq "EventTarget") { $implIncludes{"V8Node.h"} = 1; # EventTarget is not in DOM hierarchy, but all Nodes are EventTarget. - return "V8Node::HasInstance($value) ? v8DOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast($value)) : 0"; + return "V8Node::HasInstance($value) ? V8Node::toNative(v8::Handle<v8::Object>::Cast($value)) : 0"; } if ($type eq "XPathNSResolver") { @@ -2061,14 +2390,13 @@ sub JSValueToNative } AddIncludesForType($type); - # $implIncludes{"$type.h"} = 1 unless AvoidInclusionOfType($type); if (IsDOMNodeType($type)) { $implIncludes{"V8${type}.h"} = 1; # Perform type checks on the parameter, if it is expected Node type, # return NULL. - return "V8${type}::HasInstance($value) ? v8DOMWrapperToNode<${type}>(v8::Handle<v8::Object>::Cast($value)) : 0"; + 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); @@ -2087,7 +2415,7 @@ sub JSValueToNative # Perform type checks on the parameter, if it is expected Node type, # return NULL. - return "V8${type}::HasInstance($value) ? v8DOMWrapperTo<${implClassName}>(V8ClassIndex::${classIndex}, v8::Handle<v8::Object>::Cast($value)) : 0"; + return "V8${type}::HasInstance($value) ? V8${type}::toNative(v8::Handle<v8::Object>::Cast($value)) : 0"; } } @@ -2157,10 +2485,14 @@ my %non_wrapper_types = ( 'long' => 1, 'unsigned long' => 1, 'boolean' => 1, + 'long long' => 1, + 'unsigned long long' => 1, 'DOMString' => 1, 'CompareHow' => 1, + 'SVGAngle' => 1, 'SVGRect' => 1, 'SVGPoint' => 1, + 'SVGPreserveAspectRatio' => 1, 'SVGMatrix' => 1, 'SVGTransform' => 1, 'SVGLength' => 1, @@ -2228,6 +2560,7 @@ 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 v8::Number::New($value)" if $codeGenerator->IsPrimitiveType($type) or $type eq "SVGPaintType"; if ($codeGenerator->IsStringType($type)) { @@ -2245,7 +2578,6 @@ sub ReturnNativeToJSValue # V8 specific. my $implClassName = $type; AddIncludesForType($type); - # $implIncludes{GetImplementationFileName($type)} = 1 unless AvoidInclusionOfType($type); # special case for non-DOM node interfaces if (IsDOMNodeType($type)) { @@ -2270,7 +2602,7 @@ sub ReturnNativeToJSValue if ($type eq "SerializedScriptValue") { $implIncludes{"$type.h"} = 1; - return "return v8String($value->toString())"; + return "return $value->deserialize()"; } if ($type eq "DedicatedWorkerContext" or $type eq "WorkerContext" or $type eq "SharedWorkerContext") { diff --git a/WebCore/bindings/scripts/IDLParser.pm b/WebCore/bindings/scripts/IDLParser.pm index 5affe94..b2577d2 100644 --- a/WebCore/bindings/scripts/IDLParser.pm +++ b/WebCore/bindings/scripts/IDLParser.pm @@ -158,6 +158,7 @@ sub parseExtendedAttributes # Attributes with no value are set to be true $value = 1 unless defined $value; $attrs{$name} = $value; + die("Invalid extended attribute name: '$name'\n") if $name =~ /\s/; } return \%attrs; @@ -370,7 +371,9 @@ sub DetermineParseMode $mode = MODE_INTERFACE; } elsif ($_ =~ /exception/) { $mode = MODE_EXCEPTION; - } elsif ($_ =~ /alias/) { + } elsif ($_ =~ /(\A|\b)alias/) { + # The (\A|\b) above is needed so we don't match attributes + # whose names contain the substring "alias". $mode = MODE_ALIAS; } diff --git a/WebCore/bindings/scripts/generate-bindings.pl b/WebCore/bindings/scripts/generate-bindings.pl index c7adeb3..ad29dc5 100755 --- a/WebCore/bindings/scripts/generate-bindings.pl +++ b/WebCore/bindings/scripts/generate-bindings.pl @@ -56,7 +56,6 @@ my $idlFile = $ARGV[0]; die('Must specify input file.') unless defined($idlFile); die('Must specify IDL search path.') unless @idlDirectories; die('Must specify generator') unless defined($generator); -die('Must specify input file.') unless defined($idlFile); die('Must specify output directory.') unless defined($outputDirectory); die('Must specify defines') unless defined($defines); diff --git a/WebCore/bindings/v8/DOMData.cpp b/WebCore/bindings/v8/DOMData.cpp index ec9a938..417426f 100644 --- a/WebCore/bindings/v8/DOMData.cpp +++ b/WebCore/bindings/v8/DOMData.cpp @@ -33,6 +33,7 @@ #include "ChildThreadDOMData.h" #include "MainThreadDOMData.h" +#include "WebGLContextAttributes.h" #include "WebGLUniformLocation.h" namespace WebCore { diff --git a/WebCore/bindings/v8/DOMData.h b/WebCore/bindings/v8/DOMData.h index 4947e82..7fa9e7d 100644 --- a/WebCore/bindings/v8/DOMData.h +++ b/WebCore/bindings/v8/DOMData.h @@ -51,7 +51,7 @@ namespace WebCore { virtual DOMDataStore& getStore() = 0; template<typename T> - static void handleWeakObject(DOMDataStore::DOMWrapperMapType, v8::Handle<v8::Object>, T* domObject); + static void handleWeakObject(DOMDataStore::DOMWrapperMapType, v8::Persistent<v8::Object>, T* domObject); void forgetDelayedObject(void* object) { m_delayedObjectMap.take(object); } @@ -62,7 +62,7 @@ namespace WebCore { void derefDelayedObjects(); template<typename T> - static void removeObjectsFromWrapperMap(DOMWrapperMap<T>& domMap); + static void removeObjectsFromWrapperMap(AbstractWeakReferenceMap<T, v8::Object>& domMap); ThreadIdentifier owningThread() const { return m_owningThread; } @@ -72,6 +72,17 @@ namespace WebCore { void ensureDeref(V8ClassIndex::V8WrapperType type, void* domObject); static void derefObject(V8ClassIndex::V8WrapperType 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); + 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; @@ -85,7 +96,7 @@ namespace WebCore { }; template<typename T> - void DOMData::handleWeakObject(DOMDataStore::DOMWrapperMapType mapType, v8::Handle<v8::Object> v8Object, T* domObject) + void DOMData::handleWeakObject(DOMDataStore::DOMWrapperMapType mapType, v8::Persistent<v8::Object> v8Object, T* domObject) { ASSERT(WTF::isMainThread()); DOMDataList& list = DOMDataStore::allStores(); @@ -94,10 +105,7 @@ namespace WebCore { DOMDataStore::InternalDOMWrapperMap<T>* domMap = static_cast<DOMDataStore::InternalDOMWrapperMap<T>*>(store->getDOMWrapperMap(mapType)); - v8::Handle<v8::Object> wrapper = domMap->get(domObject); - if (*wrapper == *v8Object) { - // Clear the JS reference. - domMap->forgetOnly(domObject); + if (domMap->removeIfPresent(domObject, v8Object)) { ASSERT(store->domData()->owningThread() == WTF::currentThread()); store->domData()->derefObject(V8DOMWrapper::domWrapperType(v8Object), domObject); } @@ -105,21 +113,11 @@ namespace WebCore { } template<typename T> - void DOMData::removeObjectsFromWrapperMap(DOMWrapperMap<T>& domMap) + void DOMData::removeObjectsFromWrapperMap(AbstractWeakReferenceMap<T, v8::Object>& domMap) { - for (typename WTF::HashMap<T*, v8::Object*>::iterator iter(domMap.impl().begin()); iter != domMap.impl().end(); ++iter) { - T* domObject = static_cast<T*>(iter->first); - v8::Persistent<v8::Object> v8Object(iter->second); - - V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(v8::Handle<v8::Object>::Cast(v8Object)); - - // Deref the DOM object. - derefObject(type, domObject); - - // Clear the JS wrapper. - v8Object.Dispose(); - } - domMap.impl().clear(); + WrapperMapObjectRemover<T> remover; + domMap.visit(&remover); + domMap.clear(); } } // namespace WebCore diff --git a/WebCore/bindings/v8/DOMDataStore.cpp b/WebCore/bindings/v8/DOMDataStore.cpp index a76ca53..e181ebc 100644 --- a/WebCore/bindings/v8/DOMDataStore.cpp +++ b/WebCore/bindings/v8/DOMDataStore.cpp @@ -146,14 +146,14 @@ void DOMDataStore::weakDOMObjectCallback(v8::Persistent<v8::Value> v8Object, voi { v8::HandleScope scope; ASSERT(v8Object->IsObject()); - DOMData::handleWeakObject(DOMDataStore::DOMObjectMap, v8::Handle<v8::Object>::Cast(v8Object), domObject); + DOMData::handleWeakObject(DOMDataStore::DOMObjectMap, v8::Persistent<v8::Object>::Cast(v8Object), domObject); } void DOMDataStore::weakActiveDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject) { v8::HandleScope scope; ASSERT(v8Object->IsObject()); - DOMData::handleWeakObject(DOMDataStore::ActiveDOMObjectMap, v8::Handle<v8::Object>::Cast(v8Object), domObject); + DOMData::handleWeakObject(DOMDataStore::ActiveDOMObjectMap, v8::Persistent<v8::Object>::Cast(v8Object), domObject); } void DOMDataStore::weakNodeCallback(v8::Persistent<v8::Value> v8Object, void* domObject) @@ -166,32 +166,42 @@ void DOMDataStore::weakNodeCallback(v8::Persistent<v8::Value> v8Object, void* do DOMDataList& list = DOMDataStore::allStores(); for (size_t i = 0; i < list.size(); ++i) { DOMDataStore* store = list[i]; - HashMap<Node*, v8::Object*>& domMapImpl = store->domNodeMap().impl(); - HashMap<Node*, v8::Object*>::iterator it = domMapImpl.find(node); - if (it == domMapImpl.end() || it->second != *v8Object) - continue; - ASSERT(store->domData()->owningThread() == WTF::currentThread()); - v8Object.Dispose(); - domMapImpl.remove(it); - node->deref(); // Nobody overrides Node::deref so it's safe - break; // There might be at most one wrapper for the node in world's maps + if (store->domNodeMap().removeIfPresent(node, v8Object)) { + ASSERT(store->domData()->owningThread() == WTF::currentThread()); + node->deref(); // Nobody overrides Node::deref so it's safe + break; // There might be at most one wrapper for the node in world's maps + } } } +bool DOMDataStore::IntrusiveDOMWrapperMap::removeIfPresent(Node* obj, v8::Persistent<v8::Data> value) +{ + ASSERT(obj); + v8::Persistent<v8::Object>* entry = obj->wrapper(); + if (!entry) + return false; + if (*entry != value) + return false; + obj->clearWrapper(); + m_table.remove(entry); + value.Dispose(); + return true; +} + #if ENABLE(SVG) void DOMDataStore::weakSVGElementInstanceCallback(v8::Persistent<v8::Value> v8Object, void* domObject) { v8::HandleScope scope; ASSERT(v8Object->IsObject()); - DOMData::handleWeakObject(DOMDataStore::DOMSVGElementInstanceMap, v8::Handle<v8::Object>::Cast(v8Object), static_cast<SVGElementInstance*>(domObject)); + DOMData::handleWeakObject(DOMDataStore::DOMSVGElementInstanceMap, v8::Persistent<v8::Object>::Cast(v8Object), static_cast<SVGElementInstance*>(domObject)); } void DOMDataStore::weakSVGObjectWithContextCallback(v8::Persistent<v8::Value> v8Object, void* domObject) { v8::HandleScope scope; ASSERT(v8Object->IsObject()); - DOMData::handleWeakObject(DOMDataStore::DOMSVGObjectWithContextMap, v8::Handle<v8::Object>::Cast(v8Object), domObject); + DOMData::handleWeakObject(DOMDataStore::DOMSVGObjectWithContextMap, v8::Persistent<v8::Object>::Cast(v8Object), domObject); } #endif // ENABLE(SVG) diff --git a/WebCore/bindings/v8/DOMDataStore.h b/WebCore/bindings/v8/DOMDataStore.h index b127089..54a49e7 100644 --- a/WebCore/bindings/v8/DOMDataStore.h +++ b/WebCore/bindings/v8/DOMDataStore.h @@ -32,6 +32,7 @@ #define DOMDataStore_h #include "DOMObjectsInclude.h" +#include "V8Node.h" #include <v8.h> #include <wtf/HashMap.h> @@ -49,6 +50,95 @@ namespace WebCore { typedef WTF::Vector<DOMDataStore*> DOMDataList; + template <class T, int CHUNK_SIZE, class Traits> + class ChunkedTable { + public: + ChunkedTable() : m_chunks(0), m_current(0), m_last(0) { } + + T* add(T element) + { + if (m_current == m_last) { + m_chunks = new Chunk(m_chunks); + m_current = m_chunks->m_entries; + m_last = m_current + CHUNK_SIZE; + } + ASSERT((m_chunks->m_entries <= m_current) && (m_current < m_last)); + T* p = m_current++; + *p = element; + return p; + } + + void remove(T* element) + { + ASSERT(element); + ASSERT(m_current > m_chunks->m_entries); + m_current--; + if (element != m_current) + Traits::move(element, m_current); + if (m_current == m_chunks->m_entries) { + Chunk* toDelete = m_chunks; + m_chunks = toDelete->m_previous; + m_current = m_last = m_chunks ? m_chunks->m_entries + CHUNK_SIZE : 0; + delete toDelete; + } + ASSERT(!m_chunks || ((m_chunks->m_entries < m_current) && (m_current <= m_last))); + } + + void clear() + { + if (!m_chunks) + return; + + clearEntries(m_chunks->m_entries, m_current); + Chunk* last = m_chunks; + while (true) { + Chunk* previous = last->m_previous; + if (!previous) + break; + delete last; + clearEntries(previous->m_entries, previous->m_entries + CHUNK_SIZE); + last = previous; + } + + m_chunks = last; + m_current = m_chunks->m_entries; + m_last = m_current + CHUNK_SIZE; + } + + void visit(typename Traits::Visitor* visitor) + { + if (!m_chunks) + return; + + visitEntries(m_chunks->m_entries, m_current, visitor); + for (Chunk* chunk = m_chunks->m_previous; chunk; chunk = chunk->m_previous) + visitEntries(chunk->m_entries, chunk->m_entries + CHUNK_SIZE, visitor); + } + + private: + struct Chunk { + explicit Chunk(Chunk* previous) : m_previous(previous) { } + Chunk* const m_previous; + T m_entries[CHUNK_SIZE]; + }; + + static void clearEntries(T* first, T* last) + { + for (T* entry = first; entry < last; entry++) + Traits::clear(entry); + } + + static void visitEntries(T* first, T* last, typename Traits::Visitor* visitor) + { + for (T* entry = first; entry < last; entry++) + Traits::visit(entry, visitor); + } + + Chunk* m_chunks; + T* m_current; + T* m_last; + }; + // DOMDataStore // // DOMDataStore is the backing store that holds the maps between DOM objects @@ -82,12 +172,83 @@ namespace WebCore { forgetDelayedObject(m_domData, object); } - void forgetOnly(KeyType* object) { DOMWrapperMap<KeyType>::forget(object); } - private: DOMData* m_domData; }; + class IntrusiveDOMWrapperMap : public AbstractWeakReferenceMap<Node, v8::Object> { + public: + IntrusiveDOMWrapperMap(v8::WeakReferenceCallback callback) + : AbstractWeakReferenceMap<Node, v8::Object>(callback) { } + + virtual v8::Persistent<v8::Object> get(Node* obj) + { + v8::Persistent<v8::Object>* wrapper = obj->wrapper(); + return wrapper ? *wrapper : v8::Persistent<v8::Object>(); + } + + virtual void set(Node* obj, v8::Persistent<v8::Object> wrapper) + { + ASSERT(obj); + ASSERT(!obj->wrapper()); + v8::Persistent<v8::Object>* entry = m_table.add(wrapper); + obj->setWrapper(entry); + wrapper.MakeWeak(obj, weakReferenceCallback()); + } + + virtual bool contains(Node* obj) + { + return obj->wrapper(); + } + + virtual void visit(Visitor* visitor) + { + m_table.visit(visitor); + } + + virtual bool removeIfPresent(Node* key, v8::Persistent<v8::Data> value); + + virtual void clear() + { + m_table.clear(); + } + + private: + static int const numberOfEntries = (1 << 10) - 1; + + struct ChunkedTableTraits { + typedef IntrusiveDOMWrapperMap::Visitor Visitor; + + static void move(v8::Persistent<v8::Object>* target, v8::Persistent<v8::Object>* source) + { + *target = *source; + Node* node = V8Node::toNative(*target); + ASSERT(node); + node->setWrapper(target); + } + + static void clear(v8::Persistent<v8::Object>* entry) + { + Node* node = V8Node::toNative(*entry); + ASSERT(node->wrapper() == entry); + + node->clearWrapper(); + entry->Dispose(); + } + + static void visit(v8::Persistent<v8::Object>* entry, Visitor* visitor) + { + Node* node = V8Node::toNative(*entry); + ASSERT(node->wrapper() == entry); + + visitor->visitDOMWrapper(node, *entry); + } + }; + + typedef ChunkedTable<v8::Persistent<v8::Object>, numberOfEntries, ChunkedTableTraits> Table; + Table m_table; + }; + DOMDataStore(DOMData*); virtual ~DOMDataStore(); @@ -104,7 +265,7 @@ namespace WebCore { void* getDOMWrapperMap(DOMWrapperMapType); - InternalDOMWrapperMap<Node>& domNodeMap() { return *m_domNodeMap; } + DOMNodeMapping& domNodeMap() { return *m_domNodeMap; } InternalDOMWrapperMap<void>& domObjectMap() { return *m_domObjectMap; } InternalDOMWrapperMap<void>& activeDomObjectMap() { return *m_activeDomObjectMap; } #if ENABLE(SVG) @@ -124,7 +285,7 @@ namespace WebCore { static void weakSVGObjectWithContextCallback(v8::Persistent<v8::Value> v8Object, void* domObject); #endif - InternalDOMWrapperMap<Node>* m_domNodeMap; + DOMNodeMapping* m_domNodeMap; InternalDOMWrapperMap<void>* m_domObjectMap; InternalDOMWrapperMap<void>* m_activeDomObjectMap; #if ENABLE(SVG) diff --git a/WebCore/bindings/v8/DOMObjectsInclude.h b/WebCore/bindings/v8/DOMObjectsInclude.h index bded7f2..8f1b43d 100644 --- a/WebCore/bindings/v8/DOMObjectsInclude.h +++ b/WebCore/bindings/v8/DOMObjectsInclude.h @@ -34,6 +34,7 @@ #include "Attr.h" #include "BarInfo.h" #include "BeforeLoadEvent.h" +#include "Blob.h" #include "WebGLActiveInfo.h" #include "WebGLArray.h" #include "WebGLArrayBuffer.h" @@ -128,6 +129,7 @@ #include "PageTransitionEvent.h" #include "Plugin.h" #include "PluginArray.h" +#include "PopStateEvent.h" #include "ProcessingInstruction.h" #include "ProgressEvent.h" #include "Range.h" @@ -186,12 +188,23 @@ #include "StorageEvent.h" #endif // DOM_STORAGE +#if ENABLE(EVENTSOURCE) +#include "EventSource.h" +#endif // EVENTSOURCE + // GEOLOCATION #include "Coordinates.h" #include "Geolocation.h" #include "Geoposition.h" #include "PositionError.h" +#if ENABLE(INDEXED_DATABASE) +#include "IDBDatabaseError.h" +#include "IDBDatabaseException.h" +#include "IDBRequest.h" +#include "IndexedDatabaseRequest.h" +#endif // DATABASE + #if ENABLE(SVG) #include "SVGAngle.h" #include "SVGAnimatedPoints.h" diff --git a/WebCore/bindings/v8/custom/V8XPathEvaluatorConstructor.cpp b/WebCore/bindings/v8/DOMWrapperWorld.cpp index 69a8635..1e9429f 100644 --- a/WebCore/bindings/v8/custom/V8XPathEvaluatorConstructor.cpp +++ b/WebCore/bindings/v8/DOMWrapperWorld.cpp @@ -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 @@ -29,17 +29,23 @@ */ #include "config.h" -#include "XPathEvaluator.h" +#include "DOMWrapperWorld.h" -#include "V8Binding.h" -#include "V8Proxy.h" +#include <wtf/StdLibExtras.h> +#include <wtf/Threading.h> namespace WebCore { -CALLBACK_FUNC_DECL(XPathEvaluatorConstructor) +DOMWrapperWorld::DOMWrapperWorld() +{ + // This class is pretty boring, huh? +} + +DOMWrapperWorld* mainThreadNormalWorld() { - INC_STATS("DOM.XPathEvaluator.Constructor"); - return V8Proxy::constructDOMObject<V8ClassIndex::XPATHEVALUATOR, XPathEvaluator>(args); + ASSERT(isMainThread()); + DEFINE_STATIC_LOCAL(RefPtr<DOMWrapperWorld>, cachedNormalWorld, (DOMWrapperWorld::create())); + return cachedNormalWorld.get(); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8ClientRectListCustom.cpp b/WebCore/bindings/v8/DOMWrapperWorld.h index 3c62e14..f54cd4e 100644 --- a/WebCore/bindings/v8/custom/V8ClientRectListCustom.cpp +++ b/WebCore/bindings/v8/DOMWrapperWorld.h @@ -28,28 +28,28 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" -#include "ClientRectList.h" - -#include "ClientRect.h" - -#include "V8Binding.h" -#include "V8CustomBinding.h" -#include "V8Proxy.h" +#ifndef DOMWrapperWorld_h +#define DOMWrapperWorld_h +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> #include <wtf/RefPtr.h> namespace WebCore { -INDEXED_PROPERTY_GETTER(ClientRectList) -{ - INC_STATS("DOM.ClientRectList.IndexedPropertyGetter"); - ClientRectList* imp = V8DOMWrapper::convertToNativeObject<ClientRectList>(V8ClassIndex::CLIENTRECTLIST, info.Holder()); - RefPtr<ClientRect> result = imp->item(index); - if (!result) - return notHandledByInterceptor(); +// This class represent a collection of DOM wrappers for a specific world. +// The base class is pretty boring because the wrappers are actually stored +// statically in V8DOMMap and garbage collected by V8 itself. +class DOMWrapperWorld : public RefCounted<DOMWrapperWorld> { +public: + static PassRefPtr<DOMWrapperWorld> create() { return adoptRef(new DOMWrapperWorld()); } - return V8DOMWrapper::convertToV8Object(V8ClassIndex::CLIENTRECT, result.release()); -} +protected: + DOMWrapperWorld(); +}; + +DOMWrapperWorld* mainThreadNormalWorld(); } // namespace WebCore + +#endif // DOMWrapperWorld_h diff --git a/WebCore/bindings/v8/DateExtension.cpp b/WebCore/bindings/v8/DateExtension.cpp index 7d8b9be..abf8967 100644 --- a/WebCore/bindings/v8/DateExtension.cpp +++ b/WebCore/bindings/v8/DateExtension.cpp @@ -116,7 +116,7 @@ v8::Handle<v8::Value> DateExtension::Setup(const v8::Arguments& args) v8::Handle<v8::Value> DateExtension::OnSleepDetected(const v8::Arguments&) { - v8::V8::TerminateExecution(); + V8Proxy::throwError(V8Proxy::GeneralError, "Too much time spent in unload handler."); return v8::Undefined(); } diff --git a/WebCore/bindings/v8/DerivedSourcesAllInOne.cpp b/WebCore/bindings/v8/DerivedSourcesAllInOne.cpp index bd2bb7b..9658b19 100644 --- a/WebCore/bindings/v8/DerivedSourcesAllInOne.cpp +++ b/WebCore/bindings/v8/DerivedSourcesAllInOne.cpp @@ -38,11 +38,13 @@ #include "bindings/V8Attr.cpp" #include "bindings/V8BarInfo.cpp" #include "bindings/V8BeforeLoadEvent.cpp" +#include "bindings/V8Blob.cpp" #include "bindings/V8WebGLActiveInfo.cpp" #include "bindings/V8WebGLArray.cpp" #include "bindings/V8WebGLArrayBuffer.cpp" #include "bindings/V8WebGLBuffer.cpp" #include "bindings/V8WebGLByteArray.cpp" +#include "bindings/V8WebGLContextAttributes.cpp" #include "bindings/V8WebGLFloatArray.cpp" #include "bindings/V8WebGLFramebuffer.cpp" #include "bindings/V8CanvasGradient.cpp" @@ -202,6 +204,7 @@ #include "bindings/V8PageTransitionEvent.cpp" #include "bindings/V8Plugin.cpp" #include "bindings/V8PluginArray.cpp" +#include "bindings/V8PopStateEvent.cpp" #include "bindings/V8PositionError.cpp" #include "bindings/V8ProcessingInstruction.cpp" #include "bindings/V8ProgressEvent.cpp" @@ -254,6 +257,13 @@ #include "bindings/V8SQLTransaction.cpp" #endif +#if ENABLE(INDEXED_DATABASE) +#include "bindings/V8IDBDatabaseError.cpp" +#include "bindings/V8IDBDatabaseException.cpp" +#include "bindings/V8IDBRequest.cpp" +#include "bindings/V8IndexedDatabaseRequest.cpp" +#endif + #if ENABLE(WORKERS) #include "bindings/V8AbstractWorker.cpp" #include "bindings/V8DedicatedWorkerContext.cpp" @@ -421,3 +431,7 @@ #include "bindings/V8InspectorBackend.cpp" #include "bindings/V8InspectorFrontendHost.cpp" #endif + +#if ENABLE(EVENTSOURCE) +#include "bindings/V8EventSource.cpp" +#endif diff --git a/WebCore/bindings/v8/custom/V8DOMParserConstructor.cpp b/WebCore/bindings/v8/IsolatedWorld.cpp index 4af5c6e..368683d 100644 --- a/WebCore/bindings/v8/custom/V8DOMParserConstructor.cpp +++ b/WebCore/bindings/v8/IsolatedWorld.cpp @@ -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 @@ -29,17 +29,20 @@ */ #include "config.h" -#include "DOMParser.h" - -#include "V8Binding.h" -#include "V8Proxy.h" +#include "IsolatedWorld.h" namespace WebCore { -CALLBACK_FUNC_DECL(DOMParserConstructor) +int IsolatedWorld::isolatedWorldCount = 0; + +IsolatedWorld::IsolatedWorld() +{ + ++isolatedWorldCount; +} + +IsolatedWorld::~IsolatedWorld() { - INC_STATS("DOM.DOMParser.Contructor"); - return V8Proxy::constructDOMObject<V8ClassIndex::DOMPARSER, DOMParser>(args); + --isolatedWorldCount; } } // namespace WebCore diff --git a/WebCore/bindings/v8/IsolatedWorld.h b/WebCore/bindings/v8/IsolatedWorld.h new file mode 100644 index 0000000..3e86437 --- /dev/null +++ b/WebCore/bindings/v8/IsolatedWorld.h @@ -0,0 +1,62 @@ +/* + * 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. + */ + +#ifndef IsolatedWorld_h +#define IsolatedWorld_h + +#include "DOMWrapperWorld.h" +#include "V8DOMMap.h" + +namespace WebCore { + +// An DOMWrapperWorld other than the thread's normal world. +class IsolatedWorld : public DOMWrapperWorld { +public: + static PassRefPtr<IsolatedWorld> create() { return adoptRef(new IsolatedWorld()); } + static int count() { return isolatedWorldCount; } + + DOMDataStore* domDataStore() const { return m_domDataStore.getStore(); } + +protected: + IsolatedWorld(); + ~IsolatedWorld(); + +private: + // The backing store for the isolated world's DOM wrappers. This class + // doesn't have visibility into the wrappers. This handle simply helps + // manage their lifetime. + DOMDataStoreHandle m_domDataStore; + + static int isolatedWorldCount; +}; + +} // namespace WebCore + +#endif // IsolatedWorld_h diff --git a/WebCore/bindings/v8/MainThreadDOMData.cpp b/WebCore/bindings/v8/MainThreadDOMData.cpp index b1b63bf..d9c865c 100644 --- a/WebCore/bindings/v8/MainThreadDOMData.cpp +++ b/WebCore/bindings/v8/MainThreadDOMData.cpp @@ -31,7 +31,7 @@ #include "config.h" #include "MainThreadDOMData.h" -#include "V8IsolatedWorld.h" +#include "V8IsolatedContext.h" namespace WebCore { @@ -53,9 +53,9 @@ DOMDataStore& MainThreadDOMData::getMainThreadStore() // so that it can be inlined by getCurrentMainThreadStore, which is // a hot spot in Dromaeo DOM tests. ASSERT(WTF::isMainThread()); - V8IsolatedWorld* world = V8IsolatedWorld::getEntered(); - if (UNLIKELY(world != 0)) - return *world->getDOMDataStore(); + V8IsolatedContext* context = V8IsolatedContext::getEntered(); + if (UNLIKELY(context != 0)) + return *context->world()->domDataStore(); return m_defaultStore; } diff --git a/WebCore/bindings/v8/NPV8Object.cpp b/WebCore/bindings/v8/NPV8Object.cpp index e222ecd..258f579 100644 --- a/WebCore/bindings/v8/NPV8Object.cpp +++ b/WebCore/bindings/v8/NPV8Object.cpp @@ -37,6 +37,7 @@ #include "V8CustomBinding.h" #include "V8GCController.h" #include "V8Helpers.h" +#include "V8Index.h" #include "V8NPUtils.h" #include "V8Proxy.h" #include "npruntime_impl.h" @@ -46,6 +47,7 @@ #include <v8.h> #include <wtf/StringExtras.h> +using WebCore::npObjectInternalFieldCount; using WebCore::toV8Context; using WebCore::toV8Proxy; using WebCore::V8ClassIndex; @@ -92,6 +94,11 @@ static v8::Local<v8::String> npIdentifierToV8Identifier(NPIdentifier name) return v8::String::New(buffer); } +NPObject* v8ObjectToNPObject(v8::Handle<v8::Object> object) +{ + return reinterpret_cast<NPObject*>(object->GetPointerFromInternalField(WebCore::v8DOMWrapperObjectIndex)); +} + static NPClass V8NPObjectClass = { NP_CLASS_STRUCT_VERSION, allocV8NPObject, freeV8NPObject, @@ -103,11 +110,11 @@ NPClass* npScriptObjectClass = &V8NPObjectClass; NPObject* npCreateV8ScriptObject(NPP npp, v8::Handle<v8::Object> object, WebCore::DOMWindow* root) { // Check to see if this object is already wrapped. - if (object->InternalFieldCount() == V8Custom::kNPObjectInternalFieldCount) { - v8::Local<v8::Value> typeIndex = object->GetInternalField(V8Custom::kDOMWrapperTypeIndex); + if (object->InternalFieldCount() == npObjectInternalFieldCount) { + v8::Local<v8::Value> typeIndex = object->GetInternalField(WebCore::v8DOMWrapperTypeIndex); if (typeIndex->IsNumber() && typeIndex->Uint32Value() == V8ClassIndex::NPOBJECT) { - NPObject* returnValue = V8DOMWrapper::convertToNativeObject<NPObject>(V8ClassIndex::NPOBJECT, object); + NPObject* returnValue = v8ObjectToNPObject(object); _NPN_RetainObject(returnValue); return returnValue; } diff --git a/WebCore/bindings/v8/NPV8Object.h b/WebCore/bindings/v8/NPV8Object.h index 62b3ba4..911987a 100644 --- a/WebCore/bindings/v8/NPV8Object.h +++ b/WebCore/bindings/v8/NPV8Object.h @@ -30,6 +30,10 @@ #ifndef NPV8Object_h #define NPV8Object_h +<<<<<<< HEAD +======= +#include "V8Index.h" +>>>>>>> webkit.org at r54127 #if PLATFORM(CHROMIUM) // FIXME: Chromium uses a different npruntime.h, which is in // the Chromium source repository under third_party/npapi/bindings. @@ -43,6 +47,8 @@ namespace WebCore { class DOMWindow; + + static const int npObjectInternalFieldCount = v8DefaultWrapperInternalFieldCount + 0; } extern NPClass* npScriptObjectClass; @@ -65,4 +71,6 @@ struct PrivateIdentifier { NPObject* npCreateV8ScriptObject(NPP, v8::Handle<v8::Object>, WebCore::DOMWindow*); +NPObject* v8ObjectToNPObject(v8::Handle<v8::Object>); + #endif // NPV8Object_h diff --git a/WebCore/bindings/v8/RuntimeEnabledFeatures.cpp b/WebCore/bindings/v8/RuntimeEnabledFeatures.cpp index b750836..e542f53 100644 --- a/WebCore/bindings/v8/RuntimeEnabledFeatures.cpp +++ b/WebCore/bindings/v8/RuntimeEnabledFeatures.cpp @@ -33,6 +33,7 @@ namespace WebCore { +<<<<<<< HEAD #if PLATFORM(ANDROID) // This should default to true, to match the behavior with JSC bool RuntimeEnabledFeatures::isDatabaseEnabled = true; @@ -44,5 +45,13 @@ bool RuntimeEnabledFeatures::isSessionStorageEnabled = true; bool RuntimeEnabledFeatures::isNotificationsEnabled = true; bool RuntimeEnabledFeatures::isApplicationCacheEnabled = true; #endif +======= +bool RuntimeEnabledFeatures::isLocalStorageEnabled = true; +bool RuntimeEnabledFeatures::isSessionStorageEnabled = true; +bool RuntimeEnabledFeatures::isNotificationsEnabled = false; +bool RuntimeEnabledFeatures::isApplicationCacheEnabled = false; +bool RuntimeEnabledFeatures::isGeolocationEnabled = false; +bool RuntimeEnabledFeatures::isIndexedDatabaseEnabled = false; +>>>>>>> webkit.org at r54127 } // namespace WebCore diff --git a/WebCore/bindings/v8/RuntimeEnabledFeatures.h b/WebCore/bindings/v8/RuntimeEnabledFeatures.h index d8078c5..4428004 100644 --- a/WebCore/bindings/v8/RuntimeEnabledFeatures.h +++ b/WebCore/bindings/v8/RuntimeEnabledFeatures.h @@ -36,9 +36,6 @@ namespace WebCore { // A class that stores static enablers for all experimental features class RuntimeEnabledFeatures { public: - static void setDatabaseEnabled(bool isEnabled) { isDatabaseEnabled = isEnabled; } - static bool databaseEnabled() { return isDatabaseEnabled; } - static void setLocalStorageEnabled(bool isEnabled) { isLocalStorageEnabled = isEnabled; } static bool localStorageEnabled() { return isLocalStorageEnabled; } @@ -51,15 +48,22 @@ public: static void setApplicationCacheEnabled(bool isEnabled) { isApplicationCacheEnabled = isEnabled; } static bool applicationCacheEnabled() { return isApplicationCacheEnabled; } + static void setGeolocationEnabled(bool isEnabled) { isGeolocationEnabled = isEnabled; } + static bool geolocationEnabled() { return isGeolocationEnabled; } + + static void setIndexedDatabaseEnabled(bool isEnabled) { isIndexedDatabaseEnabled = isEnabled; } + static bool indexedDatabaseEnabled() { return isIndexedDatabaseEnabled; } + private: // Never instantiate. RuntimeEnabledFeatures() { } - static bool isDatabaseEnabled; static bool isLocalStorageEnabled; static bool isSessionStorageEnabled; static bool isNotificationsEnabled; static bool isApplicationCacheEnabled; + static bool isGeolocationEnabled; + static bool isIndexedDatabaseEnabled; }; } // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptCallStack.cpp b/WebCore/bindings/v8/ScriptCallStack.cpp index d9b2fcf..21063ed 100644 --- a/WebCore/bindings/v8/ScriptCallStack.cpp +++ b/WebCore/bindings/v8/ScriptCallStack.cpp @@ -31,6 +31,8 @@ #include "config.h" #include "ScriptCallStack.h" +#include "ScriptController.h" + #include <v8.h> #include "V8Binding.h" @@ -53,7 +55,7 @@ ScriptCallStack* ScriptCallStack::create(const v8::Arguments& arguments, unsigne ScriptCallStack::ScriptCallStack(const v8::Arguments& arguments, unsigned skipArgumentCount, String sourceName, int sourceLineNumber) : m_lastCaller(String(), sourceName, sourceLineNumber, arguments, skipArgumentCount) - , m_scriptState(new ScriptState(V8Proxy::retrieveFrameForCurrentContext())) + , m_scriptState(ScriptState::current()) { } diff --git a/WebCore/bindings/v8/ScriptCallStack.h b/WebCore/bindings/v8/ScriptCallStack.h index f6a7e39..8ac394c 100644 --- a/WebCore/bindings/v8/ScriptCallStack.h +++ b/WebCore/bindings/v8/ScriptCallStack.h @@ -35,7 +35,6 @@ #include "ScriptState.h" #include "ScriptValue.h" #include <wtf/Noncopyable.h> -#include <wtf/OwnPtr.h> namespace v8 { class Arguments; @@ -52,13 +51,14 @@ namespace WebCore { // FIXME: implement retrieving and storing call stack trace unsigned size() const { return 1; } - ScriptState* state() const { return m_scriptState.get(); } + ScriptState* state() const { return m_scriptState; } + ScriptState* globalState() const { return m_scriptState; } private: ScriptCallStack(const v8::Arguments& arguments, unsigned skipArgumentCount, String sourceName, int sourceLineNumber); ScriptCallFrame m_lastCaller; - OwnPtr<ScriptState> m_scriptState; + ScriptState* m_scriptState; }; } // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptController.cpp b/WebCore/bindings/v8/ScriptController.cpp index aa38ba0..8db55a1 100644 --- a/WebCore/bindings/v8/ScriptController.cpp +++ b/WebCore/bindings/v8/ScriptController.cpp @@ -47,9 +47,11 @@ #include "npruntime_priv.h" #include "NPV8Object.h" #include "ScriptSourceCode.h" -#include "ScriptState.h" #include "Settings.h" #include "V8Binding.h" +#include "V8BindingState.h" +#include "V8Event.h" +#include "V8IsolatedContext.h" #include "V8NPObject.h" #include "V8Proxy.h" #include "Widget.h" @@ -84,7 +86,7 @@ Frame* ScriptController::retrieveFrameForCurrentContext() bool ScriptController::isSafeScript(Frame* target) { - return V8Proxy::canAccessFrame(target, true); + return V8BindingSecurity::canAccessFrame(V8BindingState::Only(), target, true); } void ScriptController::gcProtectJSWrapper(void* domObject) @@ -138,7 +140,7 @@ void ScriptController::clearScriptObjects() void ScriptController::updateSecurityOrigin() { - m_proxy->updateSecurityOrigin(); + m_proxy->windowShell()->updateSecurityOrigin(); } void ScriptController::updatePlatformScriptObjects() @@ -167,7 +169,7 @@ bool ScriptController::processingUserGesture() const v8::Handle<v8::Object> global = v8Context->Global(); v8::Handle<v8::Value> jsEvent = global->Get(v8::String::NewSymbol("event")); - Event* event = V8DOMWrapper::convertToNativeEvent(jsEvent); + Event* event = V8DOMWrapper::isDOMEventWrapper(jsEvent) ? V8Event::toNative(v8::Handle<v8::Object>::Cast(jsEvent)) : 0; // Based on code from kjs_bindings.cpp. // Note: This is more liberal than Firefox's implementation. @@ -195,6 +197,12 @@ bool ScriptController::processingUserGesture() const return false; } +bool ScriptController::anyPageIsProcessingUserGesture() const +{ + // FIXME: is this right? + return processingUserGesture(); +} + void ScriptController::evaluateInIsolatedWorld(unsigned worldID, const Vector<ScriptSourceCode>& sources) { m_proxy->evaluateInIsolatedWorld(worldID, sources, 0); @@ -205,11 +213,6 @@ void ScriptController::evaluateInIsolatedWorld(unsigned worldID, const Vector<Sc m_proxy->evaluateInIsolatedWorld(worldID, sources, extensionGroup); } -void ScriptController::evaluateInNewContext(const Vector<ScriptSourceCode>& sources, int extensionGroup) -{ - m_proxy->evaluateInNewContext(sources, extensionGroup); -} - // Evaluate a script file in the environment of this proxy. ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode) { @@ -232,7 +235,7 @@ 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 start the keep alive timer here. + // so we starot the keep alive timer here. m_frame->keepAlive(); if (object.IsEmpty() || object->IsUndefined()) @@ -288,13 +291,7 @@ void ScriptController::lowMemoryNotification() bool ScriptController::haveInterpreter() const { - return m_proxy->isContextInitialized(); -} - -bool ScriptController::isEnabled() const -{ - Settings* settings = m_proxy->frame()->settings(); - return m_proxy->frame()->loader()->client()->allowJavaScript(settings && settings->isJavaScriptEnabled() && !m_frame->loader()->isSandboxed(SandboxScripts)); + return m_proxy->windowShell()->isContextInitialized(); } PassScriptInstance ScriptController::createScriptInstanceForWidget(Widget* widget) @@ -356,13 +353,6 @@ void ScriptController::getAllWorlds(Vector<DOMWrapperWorld*>& worlds) worlds.append(mainThreadNormalWorld()); } -ScriptState* ScriptController::mainWorldScriptState() -{ - if (!m_mainWorldScriptState) - m_mainWorldScriptState.set(new ScriptState(m_frame, V8Proxy::mainWorldContext(m_frame))); - return m_mainWorldScriptState.get(); -} - static NPObject* createNoScriptObject() { notImplemented(); @@ -388,7 +378,7 @@ NPObject* ScriptController::windowScriptNPObject() if (m_windowScriptNPObject) return m_windowScriptNPObject; - if (isEnabled()) { + if (canExecuteScripts()) { // JavaScript is enabled, so there is a JavaScript window object. // Return an NPObject bound to the window object. m_windowScriptNPObject = createScriptObject(m_frame); @@ -405,7 +395,7 @@ NPObject* ScriptController::windowScriptNPObject() NPObject* ScriptController::createScriptObjectForPluginElement(HTMLPlugInElement* plugin) { // Can't create NPObjects when JavaScript is disabled. - if (!isEnabled()) + if (!canExecuteScripts()) return createNoScriptObject(); v8::HandleScope handleScope; @@ -438,7 +428,7 @@ void ScriptController::attachDebugger(void*) void ScriptController::updateDocument() { - m_proxy->updateDocument(); + m_proxy->windowShell()->updateDocument(); } } // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptController.h b/WebCore/bindings/v8/ScriptController.h index fb7bbee..b45bdef 100644 --- a/WebCore/bindings/v8/ScriptController.h +++ b/WebCore/bindings/v8/ScriptController.h @@ -42,164 +42,155 @@ #include <wtf/RefCounted.h> #include <wtf/Vector.h> +struct NPObject; + namespace WebCore { - class DOMWrapperWorld; - class Event; - class Frame; - class HTMLPlugInElement; - class ScriptSourceCode; - class ScriptState; - class String; - class Widget; - class XSSAuditor; - class ScriptController { - public: - ScriptController(Frame*); - ~ScriptController(); +class DOMWrapperWorld; +class Event; +class Frame; +class HTMLPlugInElement; +class ScriptSourceCode; +class String; +class Widget; +class XSSAuditor; - // FIXME: V8Proxy should either be folded into ScriptController - // or this accessor should be made JSProxy* - V8Proxy* proxy() { return m_proxy.get(); } +class ScriptController { +public: + ScriptController(Frame*); + ~ScriptController(); - ScriptValue executeScript(const ScriptSourceCode&); - ScriptValue executeScript(const String& script, bool forceUserGesture = false); + // FIXME: V8Proxy should either be folded into ScriptController + // or this accessor should be made JSProxy* + V8Proxy* proxy() { return m_proxy.get(); } - // Returns true if argument is a JavaScript URL. - bool executeIfJavaScriptURL(const KURL&, bool userGesture = false, bool replaceDocument = true); + ScriptValue executeScript(const ScriptSourceCode&); + ScriptValue executeScript(const String& script, bool forceUserGesture = false); - // This function must be called from the main thread. It is safe to call it repeatedly. - static void initializeThreading(); + // Returns true if argument is a JavaScript URL. + bool executeIfJavaScriptURL(const KURL&, bool userGesture = false, bool replaceDocument = true); - // Evaluate a script file in the environment of this proxy. - // If succeeded, 'succ' is set to true and result is returned - // as a string. - ScriptValue evaluate(const ScriptSourceCode&); + // This function must be called from the main thread. It is safe to call it repeatedly. + static void initializeThreading(); - void evaluateInIsolatedWorld(unsigned worldID, const Vector<ScriptSourceCode>&); + // Evaluate a script file in the environment of this proxy. + // If succeeded, 'succ' is set to true and result is returned + // as a string. + ScriptValue evaluate(const ScriptSourceCode&); - // Executes JavaScript in an isolated world. The script gets its own global scope, - // its own prototypes for intrinsic JavaScript objects (String, Array, and so-on), - // and its own wrappers for all DOM nodes and DOM constructors. - // - // If an isolated world with the specified ID already exists, it is reused. - // Otherwise, a new world is created. - // - // If the worldID is 0, a new world is always created. - // - // FIXME: Get rid of extensionGroup here. - void evaluateInIsolatedWorld(unsigned worldID, const Vector<ScriptSourceCode>&, int extensionGroup); + void evaluateInIsolatedWorld(unsigned worldID, const Vector<ScriptSourceCode>&); - // Executes JavaScript in a new context associated with the web frame. The - // script gets its own global scope and its own prototypes for intrinsic - // JavaScript objects (String, Array, and so-on). It shares the wrappers for - // all DOM nodes and DOM constructors. - void evaluateInNewContext(const Vector<ScriptSourceCode>&, int extensionGroup); + // Executes JavaScript in an isolated world. The script gets its own global scope, + // its own prototypes for intrinsic JavaScript objects (String, Array, and so-on), + // and its own wrappers for all DOM nodes and DOM constructors. + // + // If an isolated world with the specified ID already exists, it is reused. + // Otherwise, a new world is created. + // + // If the worldID is 0, a new world is always created. + // + // FIXME: Get rid of extensionGroup here. + void evaluateInIsolatedWorld(unsigned worldID, const Vector<ScriptSourceCode>&, int extensionGroup); - // Masquerade 'this' as the windowShell. - // This is a bit of a hack, but provides reasonable compatibility - // with what JSC does as well. - ScriptController* windowShell(DOMWrapperWorld*) { return this; } - ScriptController* existingWindowShell(DOMWrapperWorld*) { return this; } + // Masquerade 'this' as the windowShell. + // This is a bit of a hack, but provides reasonable compatibility + // with what JSC does as well. + ScriptController* windowShell(DOMWrapperWorld*) { return this; } + ScriptController* existingWindowShell(DOMWrapperWorld*) { return this; } - XSSAuditor* xssAuditor() { return m_XSSAuditor.get(); } + XSSAuditor* xssAuditor() { return m_XSSAuditor.get(); } - void collectGarbage(); + void collectGarbage(); - // Notify V8 that the system is running low on memory. - void lowMemoryNotification(); + // Notify V8 that the system is running low on memory. + void lowMemoryNotification(); - // Creates a property of the global object of a frame. - void bindToWindowObject(Frame*, const String& key, NPObject*); + // Creates a property of the global object of a frame. + void bindToWindowObject(Frame*, const String& key, NPObject*); - PassScriptInstance createScriptInstanceForWidget(Widget*); + PassScriptInstance createScriptInstanceForWidget(Widget*); - // Check if the javascript engine has been initialized. - bool haveInterpreter() const; + // Check if the javascript engine has been initialized. + bool haveInterpreter() const; - bool isEnabled() const; + bool canExecuteScripts(); - // FIXME: void* is a compile hack. - void attachDebugger(void*); + // FIXME: void* is a compile hack. + void attachDebugger(void*); - // --- Static methods assume we are running VM in single thread, --- - // --- and there is only one VM instance. --- + // --- Static methods assume we are running VM in single thread, --- + // --- and there is only one VM instance. --- - // Returns the frame for the entered context. See comments in - // V8Proxy::retrieveFrameForEnteredContext() for more information. - static Frame* retrieveFrameForEnteredContext(); + // Returns the frame for the entered context. See comments in + // V8Proxy::retrieveFrameForEnteredContext() for more information. + static Frame* retrieveFrameForEnteredContext(); - // Returns the frame for the current context. See comments in - // V8Proxy::retrieveFrameForEnteredContext() for more information. - static Frame* retrieveFrameForCurrentContext(); + // Returns the frame for the current context. See comments in + // V8Proxy::retrieveFrameForEnteredContext() for more information. + static Frame* retrieveFrameForCurrentContext(); - // Check whether it is safe to access a frame in another domain. - static bool isSafeScript(Frame*); + // Check whether it is safe to access a frame in another domain. + static bool isSafeScript(Frame*); - // Pass command-line flags to the JS engine. - static void setFlags(const char* string, int length); + // Pass command-line flags to the JS engine. + static void setFlags(const char* string, int length); - // Protect and unprotect the JS wrapper from garbage collected. - static void gcProtectJSWrapper(void*); - static void gcUnprotectJSWrapper(void*); + // Protect and unprotect the JS wrapper from garbage collected. + static void gcProtectJSWrapper(void*); + static void gcUnprotectJSWrapper(void*); - void finishedWithEvent(Event*); - void setEventHandlerLineNumber(int lineNumber); + void finishedWithEvent(Event*); + void setEventHandlerLineNumber(int lineNumber); - void setProcessingTimerCallback(bool processingTimerCallback) { m_processingTimerCallback = processingTimerCallback; } - bool processingUserGesture() const; + void setProcessingTimerCallback(bool processingTimerCallback) { m_processingTimerCallback = processingTimerCallback; } + bool processingUserGesture() const; + bool anyPageIsProcessingUserGesture() const; - void setPaused(bool paused) { m_paused = paused; } - bool isPaused() const { return m_paused; } + void setPaused(bool paused) { m_paused = paused; } + bool isPaused() const { return m_paused; } - const String* sourceURL() const { return m_sourceURL; } // 0 if we are not evaluating any script. + const String* sourceURL() const { return m_sourceURL; } // 0 if we are not evaluating any script. - void clearWindowShell(); - void updateDocument(); + void clearWindowShell(); + void updateDocument(); - void updateSecurityOrigin(); - void clearScriptObjects(); - void updatePlatformScriptObjects(); - void cleanupScriptObjectsForPlugin(Widget*); + void updateSecurityOrigin(); + void clearScriptObjects(); + void updatePlatformScriptObjects(); + void cleanupScriptObjectsForPlugin(Widget*); #if ENABLE(NETSCAPE_PLUGIN_API) - NPObject* createScriptObjectForPluginElement(HTMLPlugInElement*); - NPObject* windowScriptNPObject(); + NPObject* createScriptObjectForPluginElement(HTMLPlugInElement*); + NPObject* windowScriptNPObject(); #endif - // Dummy method to avoid a bunch of ifdef's in WebCore. - void evaluateInWorld(const ScriptSourceCode&, DOMWrapperWorld*) { } - static void getAllWorlds(Vector<DOMWrapperWorld*>& worlds); - - // Script state for the main world context. - ScriptState* mainWorldScriptState(); + // Dummy method to avoid a bunch of ifdef's in WebCore. + void evaluateInWorld(const ScriptSourceCode&, DOMWrapperWorld*) { } + static void getAllWorlds(Vector<DOMWrapperWorld*>& worlds); - private: - Frame* m_frame; - const String* m_sourceURL; +private: + Frame* m_frame; + const String* m_sourceURL; - bool m_inExecuteScript; + bool m_inExecuteScript; - bool m_processingTimerCallback; - bool m_paused; + bool m_processingTimerCallback; + bool m_paused; - OwnPtr<V8Proxy> m_proxy; - typedef HashMap<Widget*, NPObject*> PluginObjectMap; + OwnPtr<V8Proxy> m_proxy; + typedef HashMap<Widget*, NPObject*> PluginObjectMap; - // A mapping between Widgets and their corresponding script object. - // This list is used so that when the plugin dies, we can immediately - // invalidate all sub-objects which are associated with that plugin. - // The frame keeps a NPObject reference for each item on the list. - PluginObjectMap m_pluginObjects; + // A mapping between Widgets and their corresponding script object. + // This list is used so that when the plugin dies, we can immediately + // invalidate all sub-objects which are associated with that plugin. + // The frame keeps a NPObject reference for each item on the list. + PluginObjectMap m_pluginObjects; #if ENABLE(NETSCAPE_PLUGIN_API) - NPObject* m_windowScriptNPObject; + NPObject* m_windowScriptNPObject; #endif - // The XSSAuditor associated with this ScriptController. - OwnPtr<XSSAuditor> m_XSSAuditor; - - // Script state for the main world context. - OwnPtr<ScriptState> m_mainWorldScriptState; - }; + // The XSSAuditor associated with this ScriptController. + OwnPtr<XSSAuditor> m_XSSAuditor; +}; } // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptEventListener.cpp b/WebCore/bindings/v8/ScriptEventListener.cpp index 51d53ab..b318d2e 100644 --- a/WebCore/bindings/v8/ScriptEventListener.cpp +++ b/WebCore/bindings/v8/ScriptEventListener.cpp @@ -46,13 +46,17 @@ namespace WebCore { PassRefPtr<V8LazyEventListener> createAttributeEventListener(Node* node, Attribute* attr) { ASSERT(node); + ASSERT(attr); + if (attr->isNull()) + return 0; + int lineNumber = 1; int columnNumber = 0; String sourceURL; if (Frame* frame = node->document()->frame()) { ScriptController* scriptController = frame->script(); - if (!scriptController->isEnabled()) + if (!scriptController->canExecuteScripts()) return 0; if (!scriptController->xssAuditor()->canCreateInlineEventListener(attr->localName().string(), attr->value())) { @@ -76,12 +80,16 @@ PassRefPtr<V8LazyEventListener> createAttributeEventListener(Frame* frame, Attri if (!frame) return 0; + ASSERT(attr); + if (attr->isNull()) + return 0; + int lineNumber = 1; int columnNumber = 0; String sourceURL; ScriptController* scriptController = frame->script(); - if (!scriptController->isEnabled()) + if (!scriptController->canExecuteScripts()) return 0; if (!scriptController->xssAuditor()->canCreateInlineEventListener(attr->localName().string(), attr->value())) { diff --git a/WebCore/bindings/v8/ScriptObject.h b/WebCore/bindings/v8/ScriptObject.h index 630d3b9..a60f2a8 100644 --- a/WebCore/bindings/v8/ScriptObject.h +++ b/WebCore/bindings/v8/ScriptObject.h @@ -48,6 +48,7 @@ namespace WebCore { virtual ~ScriptObject() {} v8::Local<v8::Object> v8Object() const; + ScriptState* scriptState() const { return m_scriptState; } bool set(const String& name, const String&); bool set(const char* name, const ScriptObject&); diff --git a/WebCore/bindings/v8/ScriptScope.cpp b/WebCore/bindings/v8/ScriptScope.cpp index 727ab25..a1b13a1 100644 --- a/WebCore/bindings/v8/ScriptScope.cpp +++ b/WebCore/bindings/v8/ScriptScope.cpp @@ -33,10 +33,6 @@ #include "ScriptState.h" -#include "Document.h" -#include "Frame.h" -#include "V8Binding.h" - #include <v8.h> namespace WebCore { @@ -45,8 +41,8 @@ ScriptScope::ScriptScope(ScriptState* scriptState, bool reportExceptions) : m_context(scriptState->context()) , m_scope(m_context) , m_scriptState(scriptState) - , m_reportExceptions(reportExceptions) { + m_exceptionCatcher.SetVerbose(reportExceptions); ASSERT(!m_context.IsEmpty()); } @@ -54,11 +50,6 @@ bool ScriptScope::success() { if (!m_exceptionCatcher.HasCaught()) return true; - - v8::Local<v8::Message> message = m_exceptionCatcher.Message(); - if (m_reportExceptions) - m_scriptState->frame()->document()->reportException(toWebCoreString(message->Get()), message->GetLineNumber(), toWebCoreString(message->GetScriptResourceName())); - m_exceptionCatcher.Reset(); return false; } diff --git a/WebCore/bindings/v8/ScriptScope.h b/WebCore/bindings/v8/ScriptScope.h index 6fee458..3f9a332 100644 --- a/WebCore/bindings/v8/ScriptScope.h +++ b/WebCore/bindings/v8/ScriptScope.h @@ -49,7 +49,6 @@ namespace WebCore { v8::Context::Scope m_scope; v8::TryCatch m_exceptionCatcher; ScriptState* m_scriptState; - bool m_reportExceptions; }; } diff --git a/WebCore/bindings/v8/ScriptState.cpp b/WebCore/bindings/v8/ScriptState.cpp index 68593e7..fac1d26 100644 --- a/WebCore/bindings/v8/ScriptState.cpp +++ b/WebCore/bindings/v8/ScriptState.cpp @@ -35,22 +35,17 @@ #include "Node.h" #include "Page.h" #include "ScriptController.h" +#include "V8HiddenPropertyName.h" +#include <v8.h> #include <wtf/Assertions.h> -#include <wtf/StdLibExtras.h> namespace WebCore { -ScriptState::ScriptState(Frame* frame) - : m_frame(frame) - , m_context(v8::Persistent<v8::Context>::New(V8Proxy::mainWorldContext(frame))) -{ -} - -ScriptState::ScriptState(Frame* frame, v8::Handle<v8::Context> context) - : m_frame(frame) - , m_context(v8::Persistent<v8::Context>::New(context)) +ScriptState::ScriptState(v8::Handle<v8::Context> context) + : m_context(v8::Persistent<v8::Context>::New(context)) { + m_context.MakeWeak(this, &ScriptState::weakReferenceCallback); } ScriptState::~ScriptState() @@ -59,6 +54,49 @@ ScriptState::~ScriptState() m_context.Clear(); } +ScriptState* ScriptState::forContext(v8::Local<v8::Context> context) +{ + v8::Context::Scope contextScope(context); + + v8::Local<v8::Object> global = context->Global(); + // Skip proxy object. The proxy object will survive page navigation while we need + // an object whose lifetime consides with that of the inspected context. + global = v8::Local<v8::Object>::Cast(global->GetPrototype()); + + v8::Handle<v8::String> key = V8HiddenPropertyName::scriptState(); + v8::Local<v8::Value> val = global->GetHiddenValue(key); + if (!val.IsEmpty() && val->IsExternal()) + return static_cast<ScriptState*>(v8::External::Cast(*val)->Value()); + + ScriptState* state = new ScriptState(context); + global->SetHiddenValue(key, v8::External::New(state)); + return state; +} + +ScriptState* ScriptState::current() +{ + v8::HandleScope handleScope; + v8::Local<v8::Context> context = v8::Context::GetCurrent(); + if (context.IsEmpty()) { + ASSERT_NOT_REACHED(); + return 0; + } + return ScriptState::forContext(context); +} + +void ScriptState::weakReferenceCallback(v8::Persistent<v8::Value> object, void* parameter) +{ + ScriptState* scriptState = static_cast<ScriptState*>(parameter); + delete scriptState; +} + +ScriptState* mainWorldScriptState(Frame* frame) +{ + v8::HandleScope handleScope; + V8Proxy* proxy = frame->script()->proxy(); + return ScriptState::forContext(proxy->mainWorldContext()); +} + ScriptState* scriptStateFromNode(DOMWrapperWorld*, Node* node) { // This should be never reached with V8 bindings (WebKit only uses it @@ -70,14 +108,7 @@ ScriptState* scriptStateFromNode(DOMWrapperWorld*, Node* node) ScriptState* scriptStateFromPage(DOMWrapperWorld*, Page* page) { // This should be only reached with V8 bindings from single process layout tests. - return page->mainFrame()->script()->mainWorldScriptState(); -} - -// FIXME: Stub method so we compile. Currently called from FrameLoader.cpp. -DOMWrapperWorld* mainThreadNormalWorld() -{ - DEFINE_STATIC_LOCAL(DOMWrapperWorld, oneWorld, ()); - return &oneWorld; + return mainWorldScriptState(page->mainFrame()); } } diff --git a/WebCore/bindings/v8/ScriptState.h b/WebCore/bindings/v8/ScriptState.h index 12a1388..e71becb 100644 --- a/WebCore/bindings/v8/ScriptState.h +++ b/WebCore/bindings/v8/ScriptState.h @@ -31,6 +31,7 @@ #ifndef ScriptState_h #define ScriptState_h +#include "DOMWrapperWorld.h" #include <v8.h> #include <wtf/Noncopyable.h> #include <wtf/RefCounted.h> @@ -43,11 +44,6 @@ namespace WebCore { class ScriptState : public Noncopyable { public: - ScriptState() { } - ScriptState(Frame* frame); - ScriptState(Frame* frame, v8::Handle<v8::Context> context); - ~ScriptState(); - bool hadException() { return !m_exception.IsEmpty(); } void setException(v8::Local<v8::Value> exception) { @@ -55,29 +51,42 @@ namespace WebCore { } v8::Local<v8::Value> exception() { return m_exception; } - Frame* frame() const { return m_frame; } 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; - Frame* m_frame; v8::Persistent<v8::Context> m_context; }; + class EmptyScriptState : public ScriptState { + public: + EmptyScriptState() : ScriptState() { } + ~EmptyScriptState() { } + }; + + ScriptState* mainWorldScriptState(Frame*); + ScriptState* scriptStateFromNode(DOMWrapperWorld*, Node*); ScriptState* scriptStateFromPage(DOMWrapperWorld*, Page*); - DOMWrapperWorld* mainThreadNormalWorld(); inline DOMWrapperWorld* debuggerWorld() { return mainThreadNormalWorld(); } inline DOMWrapperWorld* pluginWorld() { return mainThreadNormalWorld(); } - // Dummy class to avoid a bunch of ifdef's in WebCore. - class DOMWrapperWorld : public RefCounted<DOMWrapperWorld> { - }; - } #endif // ScriptState_h diff --git a/WebCore/bindings/v8/ScriptValue.h b/WebCore/bindings/v8/ScriptValue.h index c0ba8d5..6a70bd7 100644 --- a/WebCore/bindings/v8/ScriptValue.h +++ b/WebCore/bindings/v8/ScriptValue.h @@ -44,11 +44,6 @@ namespace WebCore { class ScriptValue { public: - static ScriptValue quarantineValue(ScriptState* scriptState, const ScriptValue& value) - { - return value; - } - ScriptValue() {} ScriptValue(v8::Handle<v8::Value> value) diff --git a/WebCore/bindings/v8/ScriptWrappable.h b/WebCore/bindings/v8/ScriptWrappable.h new file mode 100644 index 0000000..850994a --- /dev/null +++ b/WebCore/bindings/v8/ScriptWrappable.h @@ -0,0 +1,61 @@ +/* + * 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 ScriptWrappable_h +#define ScriptWrappable_h + +#include <v8.h> + +namespace WebCore { + +class ScriptWrappable { +public: + ScriptWrappable() : m_wrapper(0) { } + + v8::Persistent<v8::Object>* wrapper() const + { + return m_wrapper; + } + + void setWrapper(v8::Persistent<v8::Object>* wrapper) + { + ASSERT(wrapper); + m_wrapper = wrapper; + } + + void clearWrapper() { m_wrapper = 0; } + +private: + v8::Persistent<v8::Object>* m_wrapper; +}; + +} // namespace WebCore + +#endif // ScriptWrappable_h diff --git a/WebCore/bindings/v8/SerializedScriptValue.cpp b/WebCore/bindings/v8/SerializedScriptValue.cpp new file mode 100644 index 0000000..bac7f20 --- /dev/null +++ b/WebCore/bindings/v8/SerializedScriptValue.cpp @@ -0,0 +1,699 @@ +/* + * 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 "SerializedScriptValue.h" + +#include "SharedBuffer.h" + +#include <v8.h> +#include <wtf/Assertions.h> +#include <wtf/RefCounted.h> +#include <wtf/Vector.h> + +// FIXME: +// - catch V8 exceptions +// - be ready to get empty handles +// - consider crashing in debug mode on deserialization errors + +namespace WebCore { + +namespace { + +typedef UChar BufferValueType; + +// Serialization format is a sequence of (tag, optional data) +// pairs. Tag always takes exactly one byte. +enum SerializationTag { + InvalidTag = '!', + PaddingTag = '\0', + UndefinedTag = '_', + NullTag = '0', + TrueTag = 'T', + FalseTag = 'F', + StringTag = 'S', + Int32Tag = 'I', + NumberTag = 'N', + ObjectTag = '{', + ArrayTag = '[', +}; + +// 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); + // Since we are not required to spot the cycle as soon as it + // happens we can check for cycles only when the current depth + // is a power of two. + return !(depth & (depth - 1)); +} + +static const int maxDepth = 20000; + +// VarInt encoding constants. +static const int varIntShift = 7; +static const int varIntMask = (1 << varIntShift) - 1; + +// ZigZag encoding helps VarInt encoding stay small for negative +// numbers with small absolute values. +class ZigZag { +public: + static uint32_t encode(uint32_t value) + { + if (value & (1U << 31)) + value = ((~value) << 1) + 1; + else + value <<= 1; + return value; + } + + static uint32_t decode(uint32_t value) + { + if (value & 1) + value = ~(value >> 1); + else + value >>= 1; + return value; + } + +private: + ZigZag(); +}; + +// Writer is responsible for serializing primitive types and storing +// information used to reconstruct composite types. +class Writer : Noncopyable { +public: + Writer() : m_position(0) + { + } + + // Write functions for primitive types. + + void writeUndefined() { append(UndefinedTag); } + + void writeNull() { append(NullTag); } + + void writeTrue() { append(TrueTag); } + + void writeFalse() { append(FalseTag); } + + void writeString(const char* data, int length) + { + append(StringTag); + doWriteUint32(static_cast<uint32_t>(length)); + append(data, length); + } + + void writeInt32(int32_t value) + { + append(Int32Tag); + doWriteUint32(ZigZag::encode(static_cast<uint32_t>(value))); + } + + void writeNumber(double number) + { + append(NumberTag); + append(reinterpret_cast<char*>(&number), sizeof(number)); + } + + // Records that a composite object can be constructed by using + // |length| previously stored values. + void endComposite(SerializationTag tag, int32_t length) + { + ASSERT(tag == ObjectTag || tag == ArrayTag); + append(tag); + doWriteUint32(static_cast<uint32_t>(length)); + } + + Vector<BufferValueType>& data() + { + fillHole(); + return m_buffer; + } + +private: + void doWriteUint32(uint32_t value) + { + while (true) { + char b = (value & varIntMask); + value >>= varIntShift; + if (!value) { + append(b); + break; + } + append(b | (1 << varIntShift)); + } + } + + void append(SerializationTag tag) + { + append(static_cast<char>(tag)); + } + + void append(char b) + { + ensureSpace(1); + *charAt(m_position++) = b; + } + + void append(const char* data, int length) + { + ensureSpace(length); + memcpy(charAt(m_position), data, length); + m_position += length; + } + + void ensureSpace(int extra) + { + COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes); + m_buffer.grow((m_position + extra + 1) / 2); // "+ 1" to round up. + } + + void fillHole() + { + COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes); + // 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); + } + + char* charAt(int position) { return reinterpret_cast<char*>(m_buffer.data()) + position; } + + Vector<BufferValueType> m_buffer; + unsigned m_position; +}; + +class Serializer { +public: + explicit Serializer(Writer& writer) + : m_writer(writer) + , m_state(0) + , m_depth(0) + { + } + + 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; + } + +private: + class StateBase : public Noncopyable { + public: + virtual ~StateBase() { } + + // 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; + + protected: + StateBase(v8::Handle<v8::Value> composite) + : m_next(0) + , m_composite(composite) + { + } + + private: + StateBase* m_next; + v8::Handle<v8::Value> m_composite; + }; + + template <typename T, SerializationTag compositeTag> + class State : public StateBase { + public: + v8::Handle<T> composite() { return handleCast<T>(StateBase::composite()); } + + virtual SerializationTag tag() const { return compositeTag; } + + protected: + explicit State(v8::Handle<T> composite) : StateBase(composite) + { + } + }; + + // Helper to clean up the state stack in case of errors. + class StackCleaner : Noncopyable { + public: + explicit StackCleaner(StateBase** stack) : m_stack(stack) + { + } + + ~StackCleaner() + { + StateBase* state = *m_stack; + while (state) { + StateBase* tmp = state->nextState(); + delete state; + state = tmp; + } + *m_stack = 0; + } + + private: + StateBase** m_stack; + }; + + class ArrayState : public State<v8::Array, ArrayTag> { + public: + ArrayState(v8::Handle<v8::Array> array) + : State<v8::Array, ArrayTag>(array) + , m_index(0) + { + } + + virtual bool isDone(int* length) + { + *length = composite()->Length(); + return static_cast<int>(m_index) >= *length; + } + + virtual v8::Local<v8::Value> advance() + { + ASSERT(m_index < composite()->Length()); + v8::HandleScope scope; + return scope.Close(composite()->Get(v8::Integer::New(m_index++))); + } + + private: + unsigned m_index; + }; + + class ObjectState : public State<v8::Object, ObjectTag> { + public: + ObjectState(v8::Handle<v8::Object> object) + : State<v8::Object, ObjectTag>(object) + , m_propertyNames(object->GetPropertyNames()) + , m_index(-1) + , m_length(0) + { + nextProperty(); + } + + virtual bool isDone(int* length) + { + *length = m_length; + return m_index >= 2 * m_propertyNames->Length(); + } + + virtual v8::Local<v8::Value> advance() + { + 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() + { + 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; + } + } + } + + 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) + { + state->setNextState(m_state); + m_state = state; + ++m_depth; + } + + StateBase* top() { return m_state; } + + void pop() + { + if (!m_state) + return; + StateBase* top = m_state; + m_state = top->nextState(); + delete top; + --m_depth; + } + + bool checkComposite(v8::Handle<v8::Value> composite) + { + if (m_depth > maxDepth) + return false; + if (!shouldCheckForCycles(m_depth)) + return true; + for (StateBase* state = top(); state; state = state->nextState()) { + if (state->composite() == composite) + return false; + } + return true; + } + + Writer& m_writer; + StateBase* m_state; + int m_depth; +}; + +// 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) + : m_buffer(buffer) + , m_length(length) + , m_position(0) + { + ASSERT(length >= 0); + } + + bool isEof() const { return m_position >= m_length; } + + bool read(SerializationTag* tag, v8::Handle<v8::Value>* value, int* length) + { + uint32_t rawLength; + if (!readTag(tag)) + return false; + switch (*tag) { + case InvalidTag: + return false; + case PaddingTag: + break; + case UndefinedTag: + *value = v8::Undefined(); + break; + case NullTag: + *value = v8::Null(); + break; + case TrueTag: + *value = v8::True(); + break; + case FalseTag: + *value = v8::False(); + break; + case StringTag: + if (!readString(value)) + return false; + break; + case Int32Tag: + if (!readInt32(value)) + return false; + break; + case NumberTag: + if (!readNumber(value)) + return false; + break; + case ObjectTag: + case ArrayTag: + if (!doReadUint32(&rawLength)) + return false; + *length = rawLength; + break; + } + return true; + } + +private: + bool readTag(SerializationTag* tag) + { + if (m_position >= m_length) + return false; + *tag = static_cast<SerializationTag>(m_buffer[m_position++]); + return true; + } + + bool readString(v8::Handle<v8::Value>* value) + { + uint32_t length; + if (!doReadUint32(&length)) + return false; + if (m_position + length > m_length) + return false; + *value = v8::String::New(m_buffer + m_position, length); + m_position += length; + return true; + } + + bool readInt32(v8::Handle<v8::Value>* value) + { + uint32_t rawValue; + if (!doReadUint32(&rawValue)) + return false; + *value = v8::Integer::New(static_cast<int32_t>(ZigZag::decode(rawValue))); + return true; + } + + bool readNumber(v8::Handle<v8::Value>* value) + { + if (m_position + sizeof(double) > m_length) + return false; + double number; + char* numberAsByteArray = reinterpret_cast<char*>(&number); + for (unsigned i = 0; i < sizeof(double); ++i) + numberAsByteArray[i] = m_buffer[m_position++]; + *value = v8::Number::New(number); + return true; + } + + bool doReadUint32(uint32_t* value) + { + *value = 0; + char currentByte; + int shift = 0; + do { + if (m_position >= m_length) + return false; + currentByte = m_buffer[m_position++]; + *value |= ((currentByte & varIntMask) << shift); + shift += varIntShift; + } while (currentByte & (1 << varIntShift)); + return true; + } + + const char* m_buffer; + const unsigned m_length; + unsigned m_position; +}; + +class Deserializer { +public: + explicit Deserializer(Reader& reader) : m_reader(reader) + { + } + + v8::Local<v8::Value> deserialize() + { + v8::HandleScope scope; + while (!m_reader.isEof()) { + if (!doDeserialize()) + return v8::Local<v8::Value>(); + } + if (stackDepth() != 1) + return v8::Local<v8::Value>(); + return scope.Close(element(0)); + } + +private: + bool doDeserialize() + { + SerializationTag tag; + v8::Local<v8::Value> value; + int length = 0; + if (!m_reader.read(&tag, &value, &length)) + return false; + 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; + } + + void push(v8::Local<v8::Value> value) { m_stack.append(value); } + + void pop(unsigned length) + { + ASSERT(length <= m_stack.size()); + m_stack.shrink(m_stack.size() - length); + } + + int stackDepth() const { return m_stack.size(); } + + v8::Local<v8::Value> element(unsigned index) + { + ASSERT(index < m_stack.size()); + return m_stack[index]; + } + + Reader& m_reader; + Vector<v8::Local<v8::Value> > m_stack; +}; + +} // namespace + +SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value) +{ + Writer writer; + Serializer serializer(writer); + if (!serializer.serialize(value)) { + // FIXME: throw exception + return; + } + m_data = StringImpl::adopt(writer.data()); +} + +SerializedScriptValue::SerializedScriptValue(String data, StringDataMode mode) +{ + if (mode == WireData) + m_data = data; + else { + ASSERT(mode == StringValue); + RefPtr<SharedBuffer> buffer = utf8Buffer(data); + Writer writer; + writer.writeString(buffer->data(), buffer->size()); + m_data = StringImpl::adopt(writer.data()); + } +} + +v8::Local<v8::Value> SerializedScriptValue::deserialize() +{ + if (!m_data.impl()) + return v8::Local<v8::Value>(); + COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes); + Reader reader(reinterpret_cast<const char*>(m_data.impl()->characters()), 2 * m_data.length()); + Deserializer deserializer(reader); + return deserializer.deserialize(); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/SerializedScriptValue.h b/WebCore/bindings/v8/SerializedScriptValue.h index 26a4199..7eb8935 100644 --- a/WebCore/bindings/v8/SerializedScriptValue.h +++ b/WebCore/bindings/v8/SerializedScriptValue.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 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 @@ -40,11 +40,26 @@ namespace WebCore { class SerializedScriptValue : public RefCounted<SerializedScriptValue> { public: - static PassRefPtr<SerializedScriptValue> create(String string) + // Creates a serialized representation of the given V8 value. + static PassRefPtr<SerializedScriptValue> create(v8::Handle<v8::Value> value) { - return adoptRef(new SerializedScriptValue(string)); + return adoptRef(new SerializedScriptValue(value)); } + // Creates a serialized value with the given data obtained from a + // prior call to toWireString(). + static PassRefPtr<SerializedScriptValue> createFromWire(String data) + { + return adoptRef(new SerializedScriptValue(data, WireData)); + } + + // Creates a serialized representation of WebCore string. + static PassRefPtr<SerializedScriptValue> create(String data) + { + return adoptRef(new SerializedScriptValue(data, StringValue)); + } + + // Creates an empty serialized value. static PassRefPtr<SerializedScriptValue> create() { return adoptRef(new SerializedScriptValue()); @@ -52,23 +67,29 @@ public: PassRefPtr<SerializedScriptValue> release() { - RefPtr<SerializedScriptValue> result = adoptRef(new SerializedScriptValue(m_data)); + RefPtr<SerializedScriptValue> result = adoptRef(new SerializedScriptValue(m_data, WireData)); m_data = String(); return result.release(); } - String toString() - { - return m_data; - } + 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(); private: - SerializedScriptValue(String string) - : m_data(string) - { - } + enum StringDataMode { + StringValue, + WireData + }; SerializedScriptValue() { } + + explicit SerializedScriptValue(v8::Handle<v8::Value>); + + SerializedScriptValue(String data, StringDataMode mode); + String m_data; }; diff --git a/WebCore/bindings/v8/StaticDOMDataStore.cpp b/WebCore/bindings/v8/StaticDOMDataStore.cpp index 3a02c0b..722051b 100644 --- a/WebCore/bindings/v8/StaticDOMDataStore.cpp +++ b/WebCore/bindings/v8/StaticDOMDataStore.cpp @@ -35,7 +35,7 @@ namespace WebCore { StaticDOMDataStore::StaticDOMDataStore(DOMData* domData) : DOMDataStore(domData) - , m_staticDomNodeMap(domData, &DOMDataStore::weakNodeCallback) + , m_staticDomNodeMap(&DOMDataStore::weakNodeCallback) , m_staticDomObjectMap(domData, &DOMDataStore::weakDOMObjectCallback) , m_staticActiveDomObjectMap(domData, &DOMDataStore::weakActiveDOMObjectCallback) #if ENABLE(SVG) diff --git a/WebCore/bindings/v8/StaticDOMDataStore.h b/WebCore/bindings/v8/StaticDOMDataStore.h index 4cd0515..64a90e0 100644 --- a/WebCore/bindings/v8/StaticDOMDataStore.h +++ b/WebCore/bindings/v8/StaticDOMDataStore.h @@ -48,7 +48,7 @@ public: StaticDOMDataStore(DOMData*); private: - InternalDOMWrapperMap<Node> m_staticDomNodeMap; + IntrusiveDOMWrapperMap m_staticDomNodeMap; InternalDOMWrapperMap<void> m_staticDomObjectMap; InternalDOMWrapperMap<void> m_staticActiveDomObjectMap; #if ENABLE(SVG) diff --git a/WebCore/bindings/v8/V8Binding.cpp b/WebCore/bindings/v8/V8Binding.cpp index 00286e5..4379230 100644 --- a/WebCore/bindings/v8/V8Binding.cpp +++ b/WebCore/bindings/v8/V8Binding.cpp @@ -41,6 +41,7 @@ #include "StringBuffer.h" #include "StringHash.h" #include "Threading.h" +#include "V8Element.h" #include "V8Proxy.h" #include <v8.h> @@ -126,16 +127,6 @@ private: #endif }; - -void* v8DOMWrapperToNative(v8::Handle<v8::Object> object) { - return object->GetPointerFromInternalField(V8Custom::kDOMWrapperObjectIndex); -} - -void* v8DOMWrapperToNative(const v8::AccessorInfo& info) { - return info.Holder()->GetPointerFromInternalField(V8Custom::kDOMWrapperObjectIndex); -} - - String v8ValueToWebCoreString(v8::Handle<v8::Value> value) { if (value->IsString()) @@ -239,6 +230,17 @@ v8::Handle<v8::Value> v8StringOrFalse(const String& str) return str.isNull() ? v8::Handle<v8::Value>(v8::False()) : v8::Handle<v8::Value>(v8String(str)); } +double toWebCoreDate(v8::Handle<v8::Value> object) +{ + return (object->IsDate() || object->IsNumber()) ? object->NumberValue() : std::numeric_limits<double>::quiet_NaN(); +} + +v8::Handle<v8::Value> v8DateOrNull(double value) +{ + if (isfinite(value)) + return v8::Date::New(value); + return v8::Null(); +} template <class S> struct StringTraits { @@ -407,7 +409,11 @@ v8::Local<v8::String> v8ExternalString(const String& string) StringCache& stringCache = getStringCache(); v8::String* cachedV8String = stringCache.get(stringImpl); if (cachedV8String) - return v8::Local<v8::String>::New(v8::Handle<v8::String>(cachedV8String)); + { + v8::Persistent<v8::String> handle(cachedV8String); + if (!handle.IsNearDeath() && !handle.IsEmpty()) + return v8::Local<v8::String>::New(handle); + } v8::Local<v8::String> newString = makeExternalString(string); if (newString.IsEmpty()) @@ -457,21 +463,42 @@ v8::Local<v8::Signature> configureTemplate(v8::Persistent<v8::FunctionTemplate>d return defaultSignature; } -void createCallback(v8::Local<v8::ObjectTemplate> proto, - const char *name, - v8::InvocationCallback callback, - v8::Handle<v8::Signature> signature, - v8::PropertyAttribute attribute) +v8::Persistent<v8::String> getToStringName() +{ + DEFINE_STATIC_LOCAL(v8::Persistent<v8::String>, value, ()); + if (value.IsEmpty()) + value = v8::Persistent<v8::String>::New(v8::String::New("toString")); + return value; +} + +static v8::Handle<v8::Value> constructorToString(const v8::Arguments& args) +{ + // The DOM constructors' toString functions grab the current toString + // for Functions by taking the toString function of itself and then + // calling it with the constructor as its receiver. This means that + // changes to the Function prototype chain or toString function are + // reflected when printing DOM constructors. The only wart is that + // changes to a DOM constructor's toString's toString will cause the + // toString of the DOM constructor itself to change. This is extremely + // obscure and unlikely to be a problem. + v8::Handle<v8::Value> value = args.Callee()->Get(getToStringName()); + if (!value->IsFunction()) + return v8::String::New(""); + return v8::Handle<v8::Function>::Cast(value)->Call(args.This(), 0, 0); +} + +v8::Persistent<v8::FunctionTemplate> getToStringTemplate() { - proto->Set(v8::String::New(name), - v8::FunctionTemplate::New(callback, v8::Handle<v8::Value>(), signature), - attribute); + DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, toStringTemplate, ()); + if (toStringTemplate.IsEmpty()) + toStringTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(constructorToString)); + return toStringTemplate; } v8::Handle<v8::Value> getElementStringAttr(const v8::AccessorInfo& info, const QualifiedName& name) { - Element *imp = v8DOMWrapperToNode<Element>(info); + Element* imp = V8Element::toNative(info.Holder()); return v8ExternalString(imp->getAttribute(name)); } @@ -479,7 +506,7 @@ void setElementStringAttr(const v8::AccessorInfo& info, const QualifiedName& name, v8::Local<v8::Value> value) { - Element* imp = v8DOMWrapperToNode<Element>(info); + Element* imp = V8Element::toNative(info.Holder()); AtomicString v = toAtomicWebCoreStringWithNullCheck(value); imp->setAttribute(name, v); } diff --git a/WebCore/bindings/v8/V8Binding.h b/WebCore/bindings/v8/V8Binding.h index de5bb4c..439dfd7 100644 --- a/WebCore/bindings/v8/V8Binding.h +++ b/WebCore/bindings/v8/V8Binding.h @@ -32,6 +32,7 @@ #define V8Binding_h #include "AtomicString.h" +#include "BindingSecurity.h" #include "MathExtras.h" #include "PlatformString.h" #include "V8DOMWrapper.h" @@ -43,72 +44,15 @@ namespace WebCore { class EventListener; class EventTarget; - - // A helper function extract native object pointer from a DOM wrapper - // and cast to the specified type. - void* v8DOMWrapperToNative(v8::Handle<v8::Object>); - - template <class C> - C* v8DOMWrapperTo(v8::Handle<v8::Object> object) - { - ASSERT(V8DOMWrapper::maybeDOMWrapper(object)); - return reinterpret_cast<C*>(v8DOMWrapperToNative(object)); - } - template <class C> - C* v8DOMWrapperToNode(v8::Handle<v8::Object> object) - { - ASSERT(V8DOMWrapper::maybeDOMWrapper(object)); - ASSERT(V8DOMWrapper::domWrapperType(object) == V8ClassIndex::NODE); - return reinterpret_cast<C*>(v8DOMWrapperToNative(object)); - } - - void* v8DOMWrapperToNative(const v8::AccessorInfo&); - - template <class C> - C* v8DOMWrapperTo(const v8::AccessorInfo& info) { - ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder())); - return reinterpret_cast<C*>(v8DOMWrapperToNative(info)); - } - template <class C> - C* v8DOMWrapperToNode(const v8::AccessorInfo& info) { - ASSERT(V8DOMWrapper::domWrapperType(info.Holder()) == V8ClassIndex::NODE); - return reinterpret_cast<C*>(v8DOMWrapperToNative(info)); - } - - template <class C> - C* v8DOMWrapperTo(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Object> object) - { - // Native event listener is per frame, it cannot be handled by this generic function. - ASSERT(type != V8ClassIndex::EVENTLISTENER); - ASSERT(type != V8ClassIndex::EVENTTARGET); - - ASSERT(V8DOMWrapper::maybeDOMWrapper(object)); - -#ifndef NDEBUG - const bool typeIsValid = -#define MAKE_CASE(TYPE, NAME) (type != V8ClassIndex::TYPE) && - DOM_NODE_TYPES(MAKE_CASE) -#if ENABLE(SVG) - SVG_NODE_TYPES(MAKE_CASE) -#endif -#undef MAKE_CASE - true; - ASSERT(typeIsValid); -#endif - - return v8DOMWrapperTo<C>(object); - } - - template <class C> - C* v8DOMWrapperTo(V8ClassIndex::V8WrapperType type, const v8::AccessorInfo& info) - { -#ifndef NDEBUG - return v8DOMWrapperTo<C>(type, info.Holder()); -#else - return reinterpret_cast<C*>(v8DOMWrapperToNative(info)); -#endif - } + class V8BindingDOMWindow; + // Instantiate binding template classes for V8. + class V8Binding { + public: + typedef v8::Handle<v8::Value> Value; + typedef V8BindingDOMWindow DOMWindow; + }; + typedef BindingSecurity<V8Binding> V8BindingSecurity; enum ExternalMode { Externalize, @@ -168,6 +112,11 @@ namespace WebCore { return static_cast<float>(value->NumberValue()); } + inline long long toInt64(v8::Local<v8::Value> value) + { + return static_cast<long long>(value->IntegerValue()); + } + // FIXME: Drop this in favor of the type specific v8ValueToWebCoreString when we rework the code generation. inline String toWebCoreString(v8::Handle<v8::Value> object) { @@ -200,6 +149,10 @@ namespace WebCore { v8::Handle<v8::Value> v8StringOrUndefined(const String& str); v8::Handle<v8::Value> v8StringOrFalse(const String& str); + + double toWebCoreDate(v8::Handle<v8::Value> object); + + v8::Handle<v8::Value> v8DateOrNull(double value); v8::Persistent<v8::FunctionTemplate> createRawTemplate(); @@ -215,20 +168,15 @@ namespace WebCore { const BatchedCallback*, size_t callbackCount); - void createCallback(v8::Local<v8::ObjectTemplate> proto, - const char *name, - v8::InvocationCallback, - v8::Handle<v8::Signature>, - v8::PropertyAttribute attributes = v8::DontDelete); - v8::Handle<v8::Value> getElementStringAttr(const v8::AccessorInfo&, const QualifiedName&); void setElementStringAttr(const v8::AccessorInfo&, const QualifiedName&, v8::Local<v8::Value>); - v8::Handle<v8::Value> getElementEventHandlerAttr(const v8::AccessorInfo&, - const AtomicString&); + + v8::Persistent<v8::String> getToStringName(); + v8::Persistent<v8::FunctionTemplate> getToStringTemplate(); // V8Parameter is an adapter class that converts V8 values to Strings // or AtomicStrings as appropriate, using multiple typecast operators. diff --git a/WebCore/bindings/v8/V8Collection.cpp b/WebCore/bindings/v8/V8Collection.cpp index c9fc9ac..2ff5c88 100644 --- a/WebCore/bindings/v8/V8Collection.cpp +++ b/WebCore/bindings/v8/V8Collection.cpp @@ -52,7 +52,7 @@ v8::Handle<v8::Value> toOptionsCollectionSetter(uint32_t index, v8::Handle<v8::V return value; } - HTMLOptionElement* element = V8DOMWrapper::convertDOMWrapperToNode<HTMLOptionElement>(v8::Handle<v8::Object>::Cast(value)); + HTMLOptionElement* element = V8HTMLOptionElement::toNative(v8::Handle<v8::Object>::Cast(value)); base->setOption(index, element, ec); V8Proxy::setDOMException(ec); diff --git a/WebCore/bindings/v8/V8Collection.h b/WebCore/bindings/v8/V8Collection.h index 0a4134e..84150d8 100644 --- a/WebCore/bindings/v8/V8Collection.h +++ b/WebCore/bindings/v8/V8Collection.h @@ -51,6 +51,11 @@ namespace WebCore { return V8DOMWrapper::convertToV8Object(type, implementation); } + template<class Collection> static Collection* toNativeCollection(v8::Local<v8::Object> object) + { + return reinterpret_cast<Collection*>(object->GetPointerFromInternalField(v8DOMWrapperObjectIndex)); + } + template<class T> static v8::Handle<v8::Value> getV8Object(PassRefPtr<T> implementation, v8::Local<v8::Value> implementationType) { return getV8Object(implementation.get(), implementationType); @@ -62,10 +67,9 @@ namespace WebCore { { // FIXME: assert object is a collection type ASSERT(V8DOMWrapper::maybeDOMWrapper(object)); - V8ClassIndex::V8WrapperType wrapperType = V8DOMWrapper::domWrapperType(object); - ASSERT(wrapperType != V8ClassIndex::NODE); - Collection* collection = V8DOMWrapper::convertToNativeObject<Collection>(wrapperType, object); - String propertyName = toWebCoreString(name); + ASSERT(V8DOMWrapper::domWrapperType(object) != V8ClassIndex::NODE); + Collection* collection = toNativeCollection<Collection>(object); + AtomicString propertyName = toAtomicWebCoreStringWithNullCheck(name); return getV8Object<ItemType>(collection->namedItem(propertyName), implementationType); } @@ -84,35 +88,14 @@ namespace WebCore { return getNamedPropertyOfCollection<Collection, ItemType>(name, info.Holder(), info.Data()); } - // A template of named property accessor of HTMLSelectElement and HTMLFormElement. - template<class Collection> static v8::Handle<v8::Value> nodeCollectionNamedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) - { - ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder())); - ASSERT(V8DOMWrapper::domWrapperType(info.Holder()) == V8ClassIndex::NODE); - v8::Handle<v8::Value> value = info.Holder()->GetRealNamedPropertyInPrototypeChain(name); - - if (!value.IsEmpty()) - return value; - - // Search local callback properties next to find IDL defined - // properties. - if (info.Holder()->HasRealNamedCallbackProperty(name)) - return notHandledByInterceptor(); - Collection* collection = V8DOMWrapper::convertDOMWrapperToNode<Collection>(info.Holder()); - String propertyName = toWebCoreString(name); - void* implementation = collection->namedItem(propertyName); - return getV8Object(implementation, info.Data()); - } - // Returns the property at the index of a collection. template<class Collection, class ItemType> static v8::Handle<v8::Value> getIndexedPropertyOfCollection(uint32_t index, v8::Local<v8::Object> object, v8::Local<v8::Value> implementationType) { // FIXME: Assert that object must be a collection type. ASSERT(V8DOMWrapper::maybeDOMWrapper(object)); - V8ClassIndex::V8WrapperType wrapperType = V8DOMWrapper::domWrapperType(object); - ASSERT(wrapperType != V8ClassIndex::NODE); - Collection* collection = V8DOMWrapper::convertToNativeObject<Collection>(wrapperType, object); + ASSERT(V8DOMWrapper::domWrapperType(object) != V8ClassIndex::NODE); + Collection* collection = toNativeCollection<Collection>(object); return getV8Object<ItemType>(collection->item(index), implementationType); } @@ -122,22 +105,12 @@ namespace WebCore { return getIndexedPropertyOfCollection<Collection, ItemType>(index, info.Holder(), info.Data()); } - // A template of index interceptor of HTMLSelectElement and HTMLFormElement. - template<class Collection> static v8::Handle<v8::Value> nodeCollectionIndexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info) - { - ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder())); - ASSERT(V8DOMWrapper::domWrapperType(info.Holder()) == V8ClassIndex::NODE); - Collection* collection = V8DOMWrapper::convertDOMWrapperToNode<Collection>(info.Holder()); - void* implementation = collection->item(index); - return getV8Object(implementation, info.Data()); - } - // Get an array containing the names of indexed properties of HTMLSelectElement and HTMLFormElement. template<class Collection> static v8::Handle<v8::Array> nodeCollectionIndexedPropertyEnumerator(const v8::AccessorInfo& info) { ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder())); ASSERT(V8DOMWrapper::domWrapperType(info.Holder()) == V8ClassIndex::NODE); - Collection* collection = V8DOMWrapper::convertDOMWrapperToNode<Collection>(info.Holder()); + Collection* collection = toNativeCollection<Collection>(info.Holder()); int length = collection->length(); v8::Handle<v8::Array> properties = v8::Array::New(length); for (int i = 0; i < length; ++i) { @@ -152,8 +125,7 @@ namespace WebCore { template<class Collection> static v8::Handle<v8::Array> collectionIndexedPropertyEnumerator(const v8::AccessorInfo& info) { ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder())); - V8ClassIndex::V8WrapperType wrapperType = V8DOMWrapper::domWrapperType(info.Holder()); - Collection* collection = V8DOMWrapper::convertToNativeObject<Collection>(wrapperType, info.Holder()); + Collection* collection = toNativeCollection<Collection>(info.Holder()); int length = collection->length(); v8::Handle<v8::Array> properties = v8::Array::New(length); for (int i = 0; i < length; ++i) { @@ -170,8 +142,7 @@ namespace WebCore { { // FIXME: assert that object must be a collection type ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder())); - V8ClassIndex::V8WrapperType wrapperType = V8DOMWrapper::domWrapperType(info.Holder()); - Collection* collection = V8DOMWrapper::convertToNativeObject<Collection>(wrapperType, info.Holder()); + Collection* collection = toNativeCollection<Collection>(info.Holder()); String result = collection->item(index); return v8StringOrNull(result); } @@ -182,8 +153,7 @@ namespace WebCore { { // FIXME: assert that object must be a collection type ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder())); - V8ClassIndex::V8WrapperType wrapperType = V8DOMWrapper::domWrapperType(info.Holder()); - Collection* collection = V8DOMWrapper::convertToNativeObject<Collection>(wrapperType, info.Holder()); + Collection* collection = toNativeCollection<Collection>(info.Holder()); String result = collection->item(index); return v8String(result); } @@ -203,17 +173,6 @@ namespace WebCore { desc->InstanceTemplate()->SetNamedPropertyHandler(collectionNamedPropertyGetter<Collection, ItemType>, 0, 0, 0, 0, v8::Integer::New(V8ClassIndex::ToInt(type))); } - - // Add named and indexed getters to the function template for a collection. - template<class Collection, class ItemType> static void setCollectionIndexedAndNamedGetters(v8::Handle<v8::FunctionTemplate> desc, V8ClassIndex::V8WrapperType type) - { - // If we interceptor before object, accessing 'length' can trigger a webkit assertion error (see fast/dom/HTMLDocument/document-special-properties.html). - desc->InstanceTemplate()->SetNamedPropertyHandler(collectionNamedPropertyGetter<Collection, ItemType>, 0, 0, 0, 0, v8::Integer::New(V8ClassIndex::ToInt(type))); - desc->InstanceTemplate()->SetIndexedPropertyHandler(collectionIndexedPropertyGetter<Collection, ItemType>, 0, 0, 0, collectionIndexedPropertyEnumerator<Collection>, - v8::Integer::New(V8ClassIndex::ToInt(type))); - } - - // Add indexed getter returning a string or null to a function template for a collection. template<class Collection> static void setCollectionStringOrNullIndexedGetter(v8::Handle<v8::FunctionTemplate> desc) { diff --git a/WebCore/bindings/v8/V8DOMMap.cpp b/WebCore/bindings/v8/V8DOMMap.cpp index acd88ec..fa2fba3 100644 --- a/WebCore/bindings/v8/V8DOMMap.cpp +++ b/WebCore/bindings/v8/V8DOMMap.cpp @@ -65,7 +65,7 @@ void enableFasterDOMStoreAccess() fasterDOMStoreAccess = true; } -DOMWrapperMap<Node>& getDOMNodeMap() +DOMNodeMapping& getDOMNodeMap() { return getDOMDataStore().domNodeMap(); } @@ -145,9 +145,7 @@ void visitDOMNodesInCurrentThread(DOMWrapperMap<Node>::Visitor* visitor) if (!store->domData()->owningThread() == WTF::currentThread()) continue; - HashMap<Node*, v8::Object*>& map = store->domNodeMap().impl(); - for (HashMap<Node*, v8::Object*>::iterator it = map.begin(); it != map.end(); ++it) - visitor->visitDOMWrapper(it->first, v8::Persistent<v8::Object>(it->second)); + store->domNodeMap().visit(visitor); } } @@ -162,9 +160,7 @@ void visitDOMObjectsInCurrentThread(DOMWrapperMap<void>::Visitor* visitor) if (!store->domData()->owningThread() == WTF::currentThread()) continue; - HashMap<void*, v8::Object*> & map = store->domObjectMap().impl(); - for (HashMap<void*, v8::Object*>::iterator it = map.begin(); it != map.end(); ++it) - visitor->visitDOMWrapper(it->first, v8::Persistent<v8::Object>(it->second)); + store->domObjectMap().visit(visitor); } } @@ -179,9 +175,7 @@ void visitActiveDOMObjectsInCurrentThread(DOMWrapperMap<void>::Visitor* visitor) if (!store->domData()->owningThread() == WTF::currentThread()) continue; - HashMap<void*, v8::Object*>& map = store->activeDomObjectMap().impl(); - for (HashMap<void*, v8::Object*>::iterator it = map.begin(); it != map.end(); ++it) - visitor->visitDOMWrapper(it->first, v8::Persistent<v8::Object>(it->second)); + store->activeDomObjectMap().visit(visitor); } } @@ -198,9 +192,7 @@ void visitDOMSVGElementInstancesInCurrentThread(DOMWrapperMap<SVGElementInstance if (!store->domData()->owningThread() == WTF::currentThread()) continue; - HashMap<SVGElementInstance*, v8::Object*> & map = store->domSvgElementInstanceMap().impl(); - for (HashMap<SVGElementInstance*, v8::Object*>::iterator it = map.begin(); it != map.end(); ++it) - visitor->visitDOMWrapper(it->first, v8::Persistent<v8::Object>(it->second)); + store->domSvgElementInstanceMap().visit(visitor); } } @@ -215,9 +207,7 @@ void visitSVGObjectsInCurrentThread(DOMWrapperMap<void>::Visitor* visitor) if (!store->domData()->owningThread() == WTF::currentThread()) continue; - HashMap<void*, v8::Object*>& map = store->domSvgObjectWithContextMap().impl(); - for (HashMap<void*, v8::Object*>::iterator it = map.begin(); it != map.end(); ++it) - visitor->visitDOMWrapper(it->first, v8::Persistent<v8::Object>(it->second)); + store->domSvgObjectWithContextMap().visit(visitor); } } diff --git a/WebCore/bindings/v8/V8DOMMap.h b/WebCore/bindings/v8/V8DOMMap.h index b6861d4..8f93127 100644 --- a/WebCore/bindings/v8/V8DOMMap.h +++ b/WebCore/bindings/v8/V8DOMMap.h @@ -41,12 +41,36 @@ namespace WebCore { class SVGElementInstance; #endif + template <class KeyType, class ValueType> class AbstractWeakReferenceMap { + public: + AbstractWeakReferenceMap(v8::WeakReferenceCallback callback) : m_weakReferenceCallback(callback) { } + + class Visitor { + public: + virtual void visitDOMWrapper(KeyType* key, v8::Persistent<ValueType> object) = 0; + }; + + virtual v8::Persistent<ValueType> get(KeyType* obj) = 0; + virtual void set(KeyType* obj, v8::Persistent<ValueType> wrapper) = 0; + virtual bool contains(KeyType* obj) = 0; + virtual void visit(Visitor* visitor) = 0; + virtual bool removeIfPresent(KeyType* key, v8::Persistent<v8::Data> value) = 0; + virtual void clear() = 0; + + v8::WeakReferenceCallback weakReferenceCallback() { return m_weakReferenceCallback; } + private: + v8::WeakReferenceCallback m_weakReferenceCallback; + }; + + typedef AbstractWeakReferenceMap<Node, v8::Object> DOMNodeMapping; + // A table of wrappers with weak pointers. // This table allows us to avoid track wrapped objects for debugging // and for ensuring that we don't double wrap the same object. - template<class KeyType, class ValueType> class WeakReferenceMap { + template<class KeyType, class ValueType> class WeakReferenceMap : public AbstractWeakReferenceMap<KeyType, ValueType> { public: - WeakReferenceMap(v8::WeakReferenceCallback callback) : m_weakReferenceCallback(callback) { } + typedef AbstractWeakReferenceMap<KeyType, ValueType> Parent; + WeakReferenceMap(v8::WeakReferenceCallback callback) : Parent(callback) { } virtual ~WeakReferenceMap() { #ifndef NDEBUG @@ -65,7 +89,7 @@ namespace WebCore { virtual void set(KeyType* obj, v8::Persistent<ValueType> wrapper) { ASSERT(!m_map.contains(obj)); - wrapper.MakeWeak(obj, m_weakReferenceCallback); + wrapper.MakeWeak(obj, Parent::weakReferenceCallback()); m_map.set(obj, *wrapper); } @@ -81,9 +105,30 @@ namespace WebCore { handle.Clear(); } + bool removeIfPresent(KeyType* key, v8::Persistent<v8::Data> value) + { + typename HashMap<KeyType*, ValueType*>::iterator it = m_map.find(key); + if (it == m_map.end() || it->second != *value) + return false; + + m_map.remove(it); + value.Dispose(); + return true; + } + + void clear() + { + m_map.clear(); + } + bool contains(KeyType* obj) { return m_map.contains(obj); } - HashMap<KeyType*, ValueType*>& impl() { return m_map; } + virtual void visit(typename Parent::Visitor* visitor) + { + typename HashMap<KeyType*, ValueType*>::iterator it = m_map.begin(); + for (; it != m_map.end(); ++it) + visitor->visitDOMWrapper(it->first, v8::Persistent<ValueType>(it->second)); + } protected: HashMap<KeyType*, ValueType*> m_map; @@ -93,12 +138,15 @@ namespace WebCore { template <class KeyType> class DOMWrapperMap : public WeakReferenceMap<KeyType, v8::Object> { public: DOMWrapperMap(v8::WeakReferenceCallback callback) : WeakReferenceMap<KeyType, v8::Object>(callback) { } +<<<<<<< HEAD class Visitor { public: virtual void visitDOMWrapper(KeyType* key, v8::Persistent<v8::Object> object) = 0; virtual ~Visitor() { } }; +======= +>>>>>>> webkit.org at r54127 }; // An opaque class that represents a set of DOM wrappers. @@ -117,7 +165,7 @@ namespace WebCore { }; // A map from DOM node to its JS wrapper. - DOMWrapperMap<Node>& getDOMNodeMap(); + DOMNodeMapping& getDOMNodeMap(); void visitDOMNodesInCurrentThread(DOMWrapperMap<Node>::Visitor*); // A map from a DOM object (non-node) to its JS wrapper. This map does not contain the DOM objects which can have pending activity (active dom objects). diff --git a/WebCore/bindings/v8/V8DOMWindowShell.cpp b/WebCore/bindings/v8/V8DOMWindowShell.cpp new file mode 100644 index 0000000..793547d --- /dev/null +++ b/WebCore/bindings/v8/V8DOMWindowShell.cpp @@ -0,0 +1,559 @@ +/* + * 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 "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" +#include "Page.h" +#include "PageGroup.h" +#include "ScriptController.h" +#include "StorageNamespace.h" +#include "V8Binding.h" +#include "V8BindingState.h" +#include "V8Collection.h" +#include "V8ConsoleMessage.h" +#include "V8CustomBinding.h" +#include "V8DOMMap.h" +#include "V8DOMWindow.h" +#include "V8HiddenPropertyName.h" +#include "V8History.h" +#include "V8Index.h" +#include "V8Location.h" +#include "V8Proxy.h" +#include "WorkerContextExecutionProxy.h" + +#include <algorithm> +#include <stdio.h> +#include <utility> +#include <v8-debug.h> +#include <v8.h> +#include <wtf/Assertions.h> +#include <wtf/OwnArrayPtr.h> +#include <wtf/StdLibExtras.h> +#include <wtf/StringExtras.h> +#include <wtf/UnusedParam.h> + +namespace WebCore { + +static void handleFatalErrorInV8() +{ + // FIXME: We temporarily deal with V8 internal error situations + // such as out-of-memory by crashing the renderer. + CRASH(); +} + +static void reportFatalErrorInV8(const char* location, const char* message) +{ + // V8 is shutdown, we cannot use V8 api. + // The only thing we can do is to disable JavaScript. + // FIXME: clean up V8Proxy and disable JavaScript. + printf("V8 error: %s (%s)\n", message, location); + handleFatalErrorInV8(); +} + +// Returns the owner frame pointer of a DOM wrapper object. It only works for +// these DOM objects requiring cross-domain access check. +static Frame* getTargetFrame(v8::Local<v8::Object> host, v8::Local<v8::Value> data) +{ + Frame* target = 0; + switch (V8ClassIndex::FromInt(data->Int32Value())) { + case V8ClassIndex::DOMWINDOW: { + v8::Handle<v8::Object> window = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, host); + if (window.IsEmpty()) + return target; + + DOMWindow* targetWindow = V8DOMWindow::toNative(window); + target = targetWindow->frame(); + break; + } + case V8ClassIndex::LOCATION: { + History* history = V8History::toNative(host); + target = history->frame(); + break; + } + case V8ClassIndex::HISTORY: { + Location* location = V8Location::toNative(host); + target = location->frame(); + break; + } + default: + break; + } + return target; +} + +static void reportUnsafeJavaScriptAccess(v8::Local<v8::Object> host, v8::AccessType type, v8::Local<v8::Value> data) +{ + Frame* target = getTargetFrame(host, data); + if (target) + V8Proxy::reportUnsafeAccessTo(target, V8Proxy::ReportLater); +} + +PassRefPtr<V8DOMWindowShell> V8DOMWindowShell::create(Frame* frame) +{ + return adoptRef(new V8DOMWindowShell(frame)); +} + +V8DOMWindowShell::V8DOMWindowShell(Frame* frame) + : m_frame(frame) +{ +} + +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(); +} + +void V8DOMWindowShell::disposeContextHandles() +{ + if (!m_context.IsEmpty()) { + m_frame->loader()->client()->didDestroyScriptContextForFrame(); + m_context.Dispose(); + m_context.Clear(); + } + + if (!m_wrapperBoilerplates.IsEmpty()) { +#ifndef NDEBUG + V8GCController::unregisterGlobalHandle(this, m_wrapperBoilerplates); +#endif + m_wrapperBoilerplates.Dispose(); + m_wrapperBoilerplates.Clear(); + } +} + +void V8DOMWindowShell::destroyGlobal() +{ + if (!m_global.IsEmpty()) { +#ifndef NDEBUG + V8GCController::unregisterGlobalHandle(this, m_global); +#endif + m_global.Dispose(); + m_global.Clear(); + } +} + +void V8DOMWindowShell::clearForClose() +{ + if (!m_context.IsEmpty()) { + v8::HandleScope handleScope; + + clearDocumentWrapper(); + disposeContextHandles(); + } +} + +void V8DOMWindowShell::clearForNavigation() +{ + if (!m_context.IsEmpty()) { + v8::HandleScope handle; + clearDocumentWrapper(); + + v8::Context::Scope contextScope(m_context); + + // Clear the document wrapper cache before turning on access checks on + // the old DOMWindow wrapper. This way, access to the document wrapper + // will be protected by the security checks on the DOMWindow wrapper. + clearDocumentWrapperCache(); + + // Turn on access check on the old DOMWindow wrapper. + v8::Handle<v8::Object> wrapper = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, m_global); + ASSERT(!wrapper.IsEmpty()); + wrapper->TurnOnAccessCheck(); + + // Separate the context from its global object. + m_context->DetachGlobal(); + + disposeContextHandles(); + } +} + +// Create a new environment and setup the global object. +// +// The global object corresponds to a DOMWindow instance. However, to +// allow properties of the JS DOMWindow instance to be shadowed, we +// use a shadow object as the global object and use the JS DOMWindow +// instance as the prototype for that shadow object. The JS DOMWindow +// instance is undetectable from javascript code because the __proto__ +// accessors skip that object. +// +// The shadow object and the DOMWindow instance are seen as one object +// from javascript. The javascript object that corresponds to a +// DOMWindow instance is the shadow object. When mapping a DOMWindow +// instance to a V8 object, we return the shadow object. +// +// To implement split-window, see +// 1) https://bugs.webkit.org/show_bug.cgi?id=17249 +// 2) https://wiki.mozilla.org/Gecko:SplitWindow +// 3) https://bugzilla.mozilla.org/show_bug.cgi?id=296639 +// we need to split the shadow object further into two objects: +// an outer window and an inner window. The inner window is the hidden +// prototype of the outer window. The inner window is the default +// global object of the context. A variable declared in the global +// scope is a property of the inner window. +// +// The outer window sticks to a Frame, it is exposed to JavaScript +// via window.window, window.self, window.parent, etc. The outer window +// has a security token which is the domain. The outer window cannot +// have its own properties. window.foo = 'x' is delegated to the +// inner window. +// +// When a frame navigates to a new page, the inner window is cut off +// the outer window, and the outer window identify is preserved for +// the frame. However, a new inner window is created for the new page. +// If there are JS code holds a closure to the old inner window, +// it won't be able to reach the outer window via its global object. +void V8DOMWindowShell::initContextIfNeeded() +{ + // Bail out if the context has already been initialized. + if (!m_context.IsEmpty()) + return; + + // Create a handle scope for all local handles. + v8::HandleScope handleScope; + + // Setup the security handlers and message listener. This only has + // to be done once. + static bool isV8Initialized = false; + if (!isV8Initialized) { + // Tells V8 not to call the default OOM handler, binding code + // will handle it. + v8::V8::IgnoreOutOfMemoryException(); + v8::V8::SetFatalErrorHandler(reportFatalErrorInV8); + + v8::V8::SetGlobalGCPrologueCallback(&V8GCController::gcPrologue); + v8::V8::SetGlobalGCEpilogueCallback(&V8GCController::gcEpilogue); + + v8::V8::AddMessageListener(&V8ConsoleMessage::handler); + + v8::V8::SetFailedAccessCheckCallbackFunction(reportUnsafeJavaScriptAccess); + + isV8Initialized = true; + } + + + m_context = createNewContext(m_global, 0); + if (m_context.IsEmpty()) + return; + + v8::Local<v8::Context> v8Context = v8::Local<v8::Context>::New(m_context); + v8::Context::Scope contextScope(v8Context); + + // Store the first global object created so we can reuse it. + if (m_global.IsEmpty()) { + m_global = v8::Persistent<v8::Object>::New(v8Context->Global()); + // Bail out if allocation of the first global objects fails. + if (m_global.IsEmpty()) { + disposeContextHandles(); + return; + } +#ifndef NDEBUG + V8GCController::registerGlobalHandle(PROXY, this, m_global); +#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()) { + disposeContextHandles(); + return; + } +#ifndef NDEBUG + V8GCController::registerGlobalHandle(PROXY, this, m_wrapperBoilerplates); +#endif + + if (!installDOMWindow(v8Context, m_frame->domWindow())) + disposeContextHandles(); + + updateDocument(); + + setSecurityToken(); + + m_frame->loader()->client()->didCreateScriptContextForFrame(); + + // FIXME: This is wrong. We should actually do this for the proper world once + // we do isolated worlds the WebCore way. + m_frame->loader()->dispatchDidClearWindowObjectInWorld(0); +} + +v8::Persistent<v8::Context> V8DOMWindowShell::createNewContext(v8::Handle<v8::Object> global, int extensionGroup) +{ + v8::Persistent<v8::Context> result; + + // The activeDocumentLoader pointer could be 0 during frame shutdown. + if (!m_frame->loader()->activeDocumentLoader()) + return result; + + // Create a new environment using an empty template for the shadow + // object. Reuse the global object if one has been created earlier. + v8::Persistent<v8::ObjectTemplate> globalTemplate = V8DOMWindow::GetShadowObjectTemplate(); + if (globalTemplate.IsEmpty()) + return result; + + // Used to avoid sleep calls in unload handlers. + if (!V8Proxy::registeredExtensionWithV8(DateExtension::get())) + V8Proxy::registerExtension(DateExtension::get(), String()); + + // Dynamically tell v8 about our extensions now. + const V8Extensions& extensions = V8Proxy::extensions(); + OwnArrayPtr<const char*> extensionNames(new const char*[extensions.size()]); + int index = 0; + for (size_t i = 0; i < extensions.size(); ++i) { + if (extensions[i].group && extensions[i].group != extensionGroup) + continue; + + // 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())) + continue; + + extensionNames[index++] = extensions[i].extension->name(); + } + v8::ExtensionConfiguration extensionConfiguration(index, extensionNames.get()); + result = v8::Context::New(&extensionConfiguration, globalTemplate, global); + + return result; +} + +bool V8DOMWindowShell::installDOMWindow(v8::Handle<v8::Context> context, DOMWindow* window) +{ + v8::Handle<v8::String> implicitProtoString = v8::String::New("__proto__"); + if (implicitProtoString.IsEmpty()) + return false; + + // 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::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); + + 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); + return true; +} + +void V8DOMWindowShell::updateDocumentWrapper(v8::Handle<v8::Value> wrapper) +{ + clearDocumentWrapper(); + + ASSERT(m_document.IsEmpty()); + m_document = v8::Persistent<v8::Value>::New(wrapper); +#ifndef NDEBUG + V8GCController::registerGlobalHandle(PROXY, this, m_document); +#endif +} + +void V8DOMWindowShell::clearDocumentWrapper() +{ + if (!m_document.IsEmpty()) { +#ifndef NDEBUG + V8GCController::unregisterGlobalHandle(this, m_document); +#endif + m_document.Dispose(); + m_document.Clear(); + } +} + +void V8DOMWindowShell::updateDocumentWrapperCache() +{ + v8::HandleScope handleScope; + v8::Context::Scope contextScope(m_context); + + // If the document has no frame, NodeToV8Object might get the + // document wrapper for a document that is about to be deleted. + // If the ForceSet below causes a garbage collection, the document + // might get deleted and the global handle for the document + // wrapper cleared. Using the cleared global handle will lead to + // crashes. In this case we clear the cache and let the DOMWindow + // accessor handle access to the document. + if (!m_frame->document()->frame()) { + clearDocumentWrapperCache(); + return; + } + + v8::Handle<v8::Value> documentWrapper = V8DOMWrapper::convertNodeToV8Object(m_frame->document()); + + // If instantiation of the document wrapper fails, clear the cache + // and let the DOMWindow accessor handle access to the document. + if (documentWrapper.IsEmpty()) { + clearDocumentWrapperCache(); + return; + } + m_context->Global()->ForceSet(v8::String::New("document"), documentWrapper, static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete)); +} + +void V8DOMWindowShell::clearDocumentWrapperCache() +{ + ASSERT(!m_context.IsEmpty()); + m_context->Global()->ForceDelete(v8::String::New("document")); +} + +void V8DOMWindowShell::setSecurityToken() +{ + Document* document = m_frame->document(); + // Setup security origin and security token. + if (!document) { + m_context->UseDefaultSecurityToken(); + return; + } + + // Ask the document's SecurityOrigin to generate a security token. + // If two tokens are equal, then the SecurityOrigins canAccess each other. + // If two tokens are not equal, then we have to call canAccess. + // Note: we can't use the HTTPOrigin if it was set from the DOM. + SecurityOrigin* origin = document->securityOrigin(); + String token; + if (!origin->domainWasSetInDOM()) + token = document->securityOrigin()->toString(); + + // An empty or "null" token means we always have to call + // canAccess. The toString method on securityOrigins returns the + // string "null" for empty security origins and for security + // origins that should only allow access to themselves. In this + // case, we use the global object as the security token to avoid + // calling canAccess when a script accesses its own objects. + if (token.isEmpty() || token == "null") { + m_context->UseDefaultSecurityToken(); + return; + } + + CString utf8Token = token.utf8(); + // NOTE: V8 does identity comparison in fast path, must use a symbol + // as the security token. + m_context->SetSecurityToken(v8::String::NewSymbol(utf8Token.data(), utf8Token.length())); +} + +void V8DOMWindowShell::updateDocument() +{ + if (!m_frame->document()) + return; + + if (m_global.IsEmpty()) + return; + + // There is an existing JavaScript wrapper for the global object + // of this frame. JavaScript code in other frames might hold a + // reference to this wrapper. We eagerly initialize the JavaScript + // context for the new document to make property access on the + // global object wrapper succeed. + initContextIfNeeded(); + + // Bail out if context initialization failed. + if (m_context.IsEmpty()) + return; + + // We have a new document and we need to update the cache. + updateDocumentWrapperCache(); + + updateSecurityOrigin(); +} + +void V8DOMWindowShell::updateSecurityOrigin() +{ + v8::HandleScope scope; + setSecurityToken(); +} + +v8::Handle<v8::Value> V8DOMWindowShell::getHiddenObjectPrototype(v8::Handle<v8::Context> context) +{ + return context->Global()->GetHiddenValue(V8HiddenPropertyName::objectPrototype()); +} + +void 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; + + v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(context->Global()->Get(objectString)); + v8::Handle<v8::Value> objectPrototype = object->Get(prototypeString); + + context->Global()->SetHiddenValue(hiddenObjectPrototypeString, objectPrototype); +} + +v8::Local<v8::Object> V8DOMWindowShell::createWrapperFromCacheSlowCase(V8ClassIndex::V8WrapperType 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); + return instance->Clone(); + } + return notHandledByInterceptor(); +} + +void V8DOMWindowShell::setLocation(DOMWindow* window, const String& relativeURL) +{ + Frame* frame = window->frame(); + if (!frame) + return; + + KURL url = completeURL(relativeURL); + if (url.isNull()) + return; + + if (!shouldAllowNavigation(frame)) + return; + + navigateIfAllowed(frame, url, false, false); +} + +} // WebCore diff --git a/WebCore/bindings/v8/V8DOMWindowShell.h b/WebCore/bindings/v8/V8DOMWindowShell.h new file mode 100644 index 0000000..29dd517 --- /dev/null +++ b/WebCore/bindings/v8/V8DOMWindowShell.h @@ -0,0 +1,122 @@ +/* + * 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. + */ + +#ifndef V8DOMWindowShell_h +#define V8DOMWindowShell_h + +#include "V8CustomBinding.h" +#include "V8Index.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +class DOMWindow; +class Frame; +class String; + +// V8WindowShell represents all the per-global object state for a Frame that +// persist between navigations. +class V8DOMWindowShell : public RefCounted<V8DOMWindowShell> { +public: + static PassRefPtr<V8DOMWindowShell> create(Frame*); + + v8::Handle<v8::Context> context() const { return m_context; } + + // Update document object of the frame. + void updateDocument(); + + // Update the security origin of a document + // (e.g., after setting docoument.domain). + void updateSecurityOrigin(); + + bool isContextInitialized(); + + v8::Persistent<v8::Context> createNewContext(v8::Handle<v8::Object> global, int extensionGroup); + static bool installDOMWindow(v8::Handle<v8::Context> context, DOMWindow*); + + void initContextIfNeeded(); + void updateDocumentWrapper(v8::Handle<v8::Value> wrapper); + + void clearForNavigation(); + void clearForClose(); + + void destroyGlobal(); + + static v8::Handle<v8::Value> getHiddenObjectPrototype(v8::Handle<v8::Context>); + // WARNING: Call |installHiddenObjectPrototype| only on fresh contexts! + static void 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) + { + int classIndex = V8ClassIndex::ToInt(type); + v8::Local<v8::Object> clone(m_wrapperBoilerplates->CloneElementAt(classIndex)); + return clone.IsEmpty() ? createWrapperFromCacheSlowCase(type) : clone; + } + + static void setLocation(DOMWindow*, const String& relativeURL); + +private: + V8DOMWindowShell(Frame*); + + void disposeContextHandles(); + + void setSecurityToken(); + void clearDocumentWrapper(); + + // The JavaScript wrapper for the document object is cached on the global + // object for fast access. UpdateDocumentWrapperCache sets the wrapper + // for the current document on the global object. ClearDocumentWrapperCache + // deletes the document wrapper from the global object. + void updateDocumentWrapperCache(); + void clearDocumentWrapperCache(); + + v8::Local<v8::Object> createWrapperFromCacheSlowCase(V8ClassIndex::V8WrapperType); + + 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; + + v8::Persistent<v8::Context> m_context; + v8::Persistent<v8::Object> m_global; + v8::Persistent<v8::Value> m_document; +}; + +} // namespace WebCore + +#endif // V8DOMWindowShell_h diff --git a/WebCore/bindings/v8/V8DOMWrapper.cpp b/WebCore/bindings/v8/V8DOMWrapper.cpp index 28b316a..da50af6 100644 --- a/WebCore/bindings/v8/V8DOMWrapper.cpp +++ b/WebCore/bindings/v8/V8DOMWrapper.cpp @@ -32,11 +32,16 @@ #include "V8DOMWrapper.h" #include "CSSMutableStyleDeclaration.h" +<<<<<<< HEAD +======= +#include "DOMDataStore.h" +>>>>>>> webkit.org at r54127 #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" @@ -46,10 +51,18 @@ #include "V8DOMMap.h" #include "V8DOMWindow.h" #include "V8EventListenerList.h" +#include "V8HTMLCollection.h" +#include "V8HTMLDocument.h" #include "V8Index.h" -#include "V8IsolatedWorld.h" +#include "V8IsolatedContext.h" +#include "V8MessageChannel.h" +#include "V8Location.h" +#include "V8NamedNodeMap.h" +#include "V8NodeList.h" #include "V8Proxy.h" +#include "V8StyleSheet.h" #include "WebGLArray.h" +#include "WebGLContextAttributes.h" #include "WebGLUniformLocation.h" #include "WorkerContextExecutionProxy.h" @@ -67,32 +80,36 @@ namespace WebCore { typedef HashMap<Node*, v8::Object*> DOMNodeMap; typedef HashMap<void*, v8::Object*> DOMObjectMap; -// Get the string 'toString'. -static v8::Persistent<v8::String> GetToStringName() -{ - DEFINE_STATIC_LOCAL(v8::Persistent<v8::String>, value, ()); - if (value.IsEmpty()) - value = v8::Persistent<v8::String>::New(v8::String::New("toString")); - return value; -} +#if ENABLE(SVG) -static v8::Handle<v8::Value> ConstructorToString(const v8::Arguments& args) +static V8ClassIndex::V8WrapperType downcastSVGPathSeg(void* pathSeg) { - // The DOM constructors' toString functions grab the current toString - // for Functions by taking the toString function of itself and then - // calling it with the constructor as its receiver. This means that - // changes to the Function prototype chain or toString function are - // reflected when printing DOM constructors. The only wart is that - // changes to a DOM constructor's toString's toString will cause the - // toString of the DOM constructor itself to change. This is extremely - // obscure and unlikely to be a problem. - v8::Handle<v8::Value> value = args.Callee()->Get(GetToStringName()); - if (!value->IsFunction()) - return v8::String::New(""); - return v8::Handle<v8::Function>::Cast(value)->Call(args.This(), 0, 0); + SVGPathSeg* realPathSeg = reinterpret_cast<SVGPathSeg*>(pathSeg); + + switch (realPathSeg->pathSegType()) { + case SVGPathSeg::PATHSEG_CLOSEPATH: return V8ClassIndex::SVGPATHSEGCLOSEPATH; + case SVGPathSeg::PATHSEG_MOVETO_ABS: return V8ClassIndex::SVGPATHSEGMOVETOABS; + case SVGPathSeg::PATHSEG_MOVETO_REL: return V8ClassIndex::SVGPATHSEGMOVETOREL; + case SVGPathSeg::PATHSEG_LINETO_ABS: return V8ClassIndex::SVGPATHSEGLINETOABS; + case SVGPathSeg::PATHSEG_LINETO_REL: return V8ClassIndex::SVGPATHSEGLINETOREL; + case SVGPathSeg::PATHSEG_CURVETO_CUBIC_ABS: return V8ClassIndex::SVGPATHSEGCURVETOCUBICABS; + case SVGPathSeg::PATHSEG_CURVETO_CUBIC_REL: return V8ClassIndex::SVGPATHSEGCURVETOCUBICREL; + case SVGPathSeg::PATHSEG_CURVETO_QUADRATIC_ABS: return V8ClassIndex::SVGPATHSEGCURVETOQUADRATICABS; + case SVGPathSeg::PATHSEG_CURVETO_QUADRATIC_REL: return V8ClassIndex::SVGPATHSEGCURVETOQUADRATICREL; + case SVGPathSeg::PATHSEG_ARC_ABS: return V8ClassIndex::SVGPATHSEGARCABS; + case SVGPathSeg::PATHSEG_ARC_REL: return V8ClassIndex::SVGPATHSEGARCREL; + case SVGPathSeg::PATHSEG_LINETO_HORIZONTAL_ABS: return V8ClassIndex::SVGPATHSEGLINETOHORIZONTALABS; + case SVGPathSeg::PATHSEG_LINETO_HORIZONTAL_REL: return V8ClassIndex::SVGPATHSEGLINETOHORIZONTALREL; + case SVGPathSeg::PATHSEG_LINETO_VERTICAL_ABS: return V8ClassIndex::SVGPATHSEGLINETOVERTICALABS; + case SVGPathSeg::PATHSEG_LINETO_VERTICAL_REL: return V8ClassIndex::SVGPATHSEGLINETOVERTICALREL; + case SVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_ABS: return V8ClassIndex::SVGPATHSEGCURVETOCUBICSMOOTHABS; + case SVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_REL: return V8ClassIndex::SVGPATHSEGCURVETOCUBICSMOOTHREL; + case SVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS: return V8ClassIndex::SVGPATHSEGCURVETOQUADRATICSMOOTHABS; + case SVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL: return V8ClassIndex::SVGPATHSEGCURVETOQUADRATICSMOOTHREL; + default: return V8ClassIndex::INVALID_CLASS_INDEX; + } } -#if ENABLE(SVG) v8::Handle<v8::Value> V8DOMWrapper::convertSVGElementInstanceToV8Object(SVGElementInstance* instance) { if (!instance) @@ -124,7 +141,7 @@ v8::Handle<v8::Value> V8DOMWrapper::convertSVGObjectWithContextToV8Object(V8Clas // Special case: SVGPathSegs need to be downcast to their real type if (type == V8ClassIndex::SVGPATHSEG) - type = V8Custom::DowncastSVGPathSeg(object); + type = downcastSVGPathSeg(object); v8::Local<v8::Object> v8Object = instantiateV8Object(type, type, object); if (!v8Object.IsEmpty()) { @@ -148,7 +165,7 @@ v8::Handle<v8::Value> V8DOMWrapper::convertSVGObjectWithContextToV8Object(V8Clas return result; } -#endif +#endif // ENABLE(SVG) #if ENABLE(3D_CANVAS) void V8DOMWrapper::setIndexedPropertiesToExternalArray(v8::Handle<v8::Object> wrapper, @@ -189,25 +206,6 @@ void V8DOMWrapper::setIndexedPropertiesToExternalArray(v8::Handle<v8::Object> wr } #endif -bool V8DOMWrapper::domObjectHasJSWrapper(void* object) -{ - return getDOMObjectMap().contains(object) || getActiveDOMObjectMap().contains(object); -} - -v8::Persistent<v8::Object> V8DOMWrapper::jsWrapperForDOMObject(void* object) -{ - v8::Persistent<v8::Object> wrapper = getDOMObjectMap().get(object); - ASSERT(!wrapper.IsEmpty()); - return wrapper; -} - -v8::Persistent<v8::Object> V8DOMWrapper::jsWrapperForActiveDOMObject(void* object) -{ - v8::Persistent<v8::Object> wrapper = getActiveDOMObjectMap().get(object); - ASSERT(!wrapper.IsEmpty()); - return wrapper; -} - // The caller must have increased obj's ref count. void V8DOMWrapper::setJSWrapperForDOMObject(void* object, v8::Persistent<v8::Object> wrapper) { @@ -259,6 +257,7 @@ v8::Persistent<v8::FunctionTemplate> V8DOMWrapper::getTemplate(V8ClassIndex::V8W // Not in the cache. FunctionTemplateFactory factory = V8ClassIndex::GetFactory(type); v8::Persistent<v8::FunctionTemplate> descriptor = factory(); +<<<<<<< HEAD // DOM constructors are functions and should print themselves as such. // However, we will later replace their prototypes with Object // prototypes so we need to explicitly override toString on the @@ -618,6 +617,8 @@ v8::Persistent<v8::FunctionTemplate> V8DOMWrapper::getTemplate(V8ClassIndex::V8W default: break; } +======= +>>>>>>> webkit.org at r54127 *cacheCell = descriptor; return descriptor; @@ -652,7 +653,7 @@ v8::Local<v8::Function> V8DOMWrapper::getConstructorForContext(V8ClassIndex::V8W // Enter the scope for this context to get the correct constructor. v8::Context::Scope scope(context); - return getConstructor(type, V8Proxy::getHiddenObjectPrototype(context)); + return getConstructor(type, V8DOMWindowShell::getHiddenObjectPrototype(context)); } v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType type, DOMWindow* window) @@ -813,44 +814,44 @@ v8::Handle<v8::Value> V8DOMWrapper::convertToV8Object(V8ClassIndex::V8WrapperTyp // reused by a new page. switch (type) { case V8ClassIndex::CONSOLE: - setHiddenWindowReference(static_cast<Console*>(impl)->frame(), V8Custom::kDOMWindowConsoleIndex, result); + setHiddenWindowReference(static_cast<Console*>(impl)->frame(), V8DOMWindow::consoleIndex, result); break; case V8ClassIndex::HISTORY: - setHiddenWindowReference(static_cast<History*>(impl)->frame(), V8Custom::kDOMWindowHistoryIndex, result); + setHiddenWindowReference(static_cast<History*>(impl)->frame(), V8DOMWindow::historyIndex, result); break; case V8ClassIndex::NAVIGATOR: - setHiddenWindowReference(static_cast<Navigator*>(impl)->frame(), V8Custom::kDOMWindowNavigatorIndex, result); + setHiddenWindowReference(static_cast<Navigator*>(impl)->frame(), V8DOMWindow::navigatorIndex, result); break; case V8ClassIndex::SCREEN: - setHiddenWindowReference(static_cast<Screen*>(impl)->frame(), V8Custom::kDOMWindowScreenIndex, result); + setHiddenWindowReference(static_cast<Screen*>(impl)->frame(), V8DOMWindow::screenIndex, result); break; case V8ClassIndex::LOCATION: - setHiddenWindowReference(static_cast<Location*>(impl)->frame(), V8Custom::kDOMWindowLocationIndex, result); + setHiddenWindowReference(static_cast<Location*>(impl)->frame(), V8DOMWindow::locationIndex, result); break; case V8ClassIndex::DOMSELECTION: - setHiddenWindowReference(static_cast<DOMSelection*>(impl)->frame(), V8Custom::kDOMWindowDOMSelectionIndex, result); + setHiddenWindowReference(static_cast<DOMSelection*>(impl)->frame(), V8DOMWindow::domSelectionIndex, result); break; case V8ClassIndex::BARINFO: { BarInfo* barInfo = static_cast<BarInfo*>(impl); Frame* frame = barInfo->frame(); switch (barInfo->type()) { case BarInfo::Locationbar: - setHiddenWindowReference(frame, V8Custom::kDOMWindowLocationbarIndex, result); + setHiddenWindowReference(frame, V8DOMWindow::locationbarIndex, result); break; case BarInfo::Menubar: - setHiddenWindowReference(frame, V8Custom::kDOMWindowMenubarIndex, result); + setHiddenWindowReference(frame, V8DOMWindow::menubarIndex, result); break; case BarInfo::Personalbar: - setHiddenWindowReference(frame, V8Custom::kDOMWindowPersonalbarIndex, result); + setHiddenWindowReference(frame, V8DOMWindow::personalbarIndex, result); break; case BarInfo::Scrollbars: - setHiddenWindowReference(frame, V8Custom::kDOMWindowScrollbarsIndex, result); + setHiddenWindowReference(frame, V8DOMWindow::scrollbarsIndex, result); break; case BarInfo::Statusbar: - setHiddenWindowReference(frame, V8Custom::kDOMWindowStatusbarIndex, result); + setHiddenWindowReference(frame, V8DOMWindow::statusbarIndex, result); break; case BarInfo::Toolbar: - setHiddenWindowReference(frame, V8Custom::kDOMWindowToolbarIndex, result); + setHiddenWindowReference(frame, V8DOMWindow::toolbarIndex, result); break; } break; @@ -872,7 +873,7 @@ void V8DOMWrapper::setHiddenWindowReference(Frame* frame, const int internalInde if (context.IsEmpty()) return; - ASSERT(internalIndex < V8Custom::kDOMWindowInternalFieldCount); + ASSERT(internalIndex < V8DOMWindow::internalFieldCount); v8::Handle<v8::Object> global = context->Global(); // Look for real DOM wrapper. @@ -885,15 +886,10 @@ void V8DOMWrapper::setHiddenWindowReference(Frame* frame, const int internalInde V8ClassIndex::V8WrapperType V8DOMWrapper::domWrapperType(v8::Handle<v8::Object> object) { ASSERT(V8DOMWrapper::maybeDOMWrapper(object)); - v8::Handle<v8::Value> type = object->GetInternalField(V8Custom::kDOMWrapperTypeIndex); + v8::Handle<v8::Value> type = object->GetInternalField(v8DOMWrapperTypeIndex); return V8ClassIndex::FromInt(type->Int32Value()); } -void* V8DOMWrapper::convertToSVGPODTypeImpl(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Value> object) -{ - return isWrapperOfType(object, type) ? convertDOMWrapperToNative<void>(v8::Handle<v8::Object>::Cast(object)) : 0; -} - PassRefPtr<NodeFilter> V8DOMWrapper::wrapNativeNodeFilter(v8::Handle<v8::Value> filter) { // A NodeFilter is used when walking through a DOM tree or iterating tree @@ -917,17 +913,19 @@ v8::Local<v8::Object> V8DOMWrapper::instantiateV8Object(V8Proxy* proxy, V8ClassI if (descriptorType == V8ClassIndex::HTMLCOLLECTION && static_cast<HTMLCollection*>(impl)->type() == DocAll) descriptorType = V8ClassIndex::HTMLALLCOLLECTION; - if (V8IsolatedWorld::getEntered()) { + if (V8IsolatedContext::getEntered()) { // This effectively disables the wrapper cache for isolated worlds. proxy = 0; // FIXME: Do we need a wrapper cache for the isolated world? We should - // see if the performance gains are worth while. + // see if the performance gains are worth while. + // We'll get one once we give the isolated context a proper window shell. } else if (!proxy) proxy = V8Proxy::retrieve(); v8::Local<v8::Object> instance; if (proxy) - instance = proxy->createWrapperFromCache(descriptorType); + // FIXME: Fix this to work properly with isolated worlds (see above). + instance = proxy->windowShell()->createWrapperFromCache(descriptorType); else { v8::Local<v8::Function> function = getTemplate(descriptorType)->GetFunction(); instance = SafeAllocation::newInstance(function); @@ -949,13 +947,13 @@ bool V8DOMWrapper::maybeDOMWrapper(v8::Handle<v8::Value> value) if (!object->InternalFieldCount()) return false; - ASSERT(object->InternalFieldCount() >= V8Custom::kDefaultWrapperInternalFieldCount); + ASSERT(object->InternalFieldCount() >= v8DefaultWrapperInternalFieldCount); - v8::Handle<v8::Value> type = object->GetInternalField(V8Custom::kDOMWrapperTypeIndex); + 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(V8Custom::kDOMWrapperObjectIndex); + v8::Handle<v8::Value> wrapper = object->GetInternalField(v8DOMWrapperObjectIndex); ASSERT(wrapper->IsNumber() || wrapper->IsExternal()); return true; @@ -978,12 +976,12 @@ bool V8DOMWrapper::isWrapperOfType(v8::Handle<v8::Value> value, V8ClassIndex::V8 if (!object->InternalFieldCount()) return false; - ASSERT(object->InternalFieldCount() >= V8Custom::kDefaultWrapperInternalFieldCount); + ASSERT(object->InternalFieldCount() >= v8DefaultWrapperInternalFieldCount); - v8::Handle<v8::Value> wrapper = object->GetInternalField(V8Custom::kDOMWrapperObjectIndex); + v8::Handle<v8::Value> wrapper = object->GetInternalField(v8DOMWrapperObjectIndex); ASSERT(wrapper->IsNumber() || wrapper->IsExternal()); - v8::Handle<v8::Value> type = object->GetInternalField(V8Custom::kDOMWrapperTypeIndex); + v8::Handle<v8::Value> type = object->GetInternalField(v8DOMWrapperTypeIndex); ASSERT(type->IsInt32()); ASSERT(V8ClassIndex::INVALID_CLASS_INDEX < type->Int32Value() && type->Int32Value() < V8ClassIndex::CLASSINDEX_END); @@ -1135,6 +1133,7 @@ V8ClassIndex::V8WrapperType V8DOMWrapper::htmlElementType(HTMLElement* element) macro(feImage, FEIMAGE) \ macro(feMerge, FEMERGE) \ macro(feMergeNode, FEMERGENODE) \ + macro(feMorphology, FEMORPHOLOGY) \ macro(feOffset, FEOFFSET) \ macro(fePointLight, FEPOINTLIGHT) \ macro(feSpecularLighting, FESPECULARLIGHTING) \ @@ -1274,6 +1273,8 @@ v8::Handle<v8::Value> V8DOMWrapper::convertEventToV8Object(Event* event) type = V8ClassIndex::MESSAGEEVENT; else if (event->isPageTransitionEvent()) type = V8ClassIndex::PAGETRANSITIONEVENT; + else if (event->isPopStateEvent()) + type = V8ClassIndex::POPSTATEEVENT; else if (event->isProgressEvent()) { if (event->isXMLHttpRequestProgressEvent()) type = V8ClassIndex::XMLHTTPREQUESTPROGRESSEVENT; @@ -1335,9 +1336,9 @@ v8::Handle<v8::Value> V8DOMWrapper::convertDocumentToV8Object(Document* document // checking if the node already has a wrapper. V8Proxy* proxy = V8Proxy::retrieve(document->frame()); if (proxy) - proxy->initContextIfNeeded(); + proxy->windowShell()->initContextIfNeeded(); - DOMWrapperMap<Node>& domNodeMap = getDOMNodeMap(); + DOMNodeMapping& domNodeMap = getDOMNodeMap(); v8::Handle<v8::Object> wrapper = domNodeMap.get(document); if (wrapper.IsEmpty()) return convertNewNodeToV8Object(document, proxy, domNodeMap); @@ -1345,25 +1346,39 @@ v8::Handle<v8::Value> V8DOMWrapper::convertDocumentToV8Object(Document* document return wrapper; } +static v8::Handle<v8::Value> getWrapper(Node* node) +{ + ASSERT(WTF::isMainThread()); + V8IsolatedContext* context = V8IsolatedContext::getEntered(); + if (LIKELY(!context)) { + v8::Persistent<v8::Object>* wrapper = node->wrapper(); + if (!wrapper) + return v8::Handle<v8::Value>(); + return *wrapper; + } + + DOMNodeMapping& domNodeMap = context->world()->domDataStore()->domNodeMap(); + return domNodeMap.get(node); +} + v8::Handle<v8::Value> V8DOMWrapper::convertNodeToV8Object(Node* node) { if (!node) return v8::Null(); + v8::Handle<v8::Value> wrapper = getWrapper(node); + if (!wrapper.IsEmpty()) + return wrapper; + Document* document = node->document(); if (node == document) return convertDocumentToV8Object(document); - - DOMWrapperMap<Node>& domNodeMap = getDOMNodeMap(); - v8::Handle<v8::Object> wrapper = domNodeMap.get(node); - if (wrapper.IsEmpty()) - return convertNewNodeToV8Object(node, 0, domNodeMap); - - return wrapper; + + return convertNewNodeToV8Object(node, 0, getDOMNodeMap()); } // Caller checks node is not null. -v8::Handle<v8::Value> V8DOMWrapper::convertNewNodeToV8Object(Node* node, V8Proxy* proxy, DOMWrapperMap<Node>& domNodeMap) +v8::Handle<v8::Value> V8DOMWrapper::convertNewNodeToV8Object(Node* node, V8Proxy* proxy, DOMNodeMapping& domNodeMap) { if (!proxy && node->document()) proxy = V8Proxy::retrieve(node->document()->frame()); @@ -1425,16 +1440,16 @@ v8::Handle<v8::Value> V8DOMWrapper::convertNewNodeToV8Object(Node* node, V8Proxy if (isDocument) { if (proxy) - proxy->updateDocumentWrapper(result); + proxy->windowShell()->updateDocumentWrapper(result); if (type == V8ClassIndex::HTMLDOCUMENT) { // Create marker object and insert it in two internal fields. // This is used to implement temporary shadowing of // document.all. - ASSERT(result->InternalFieldCount() == V8Custom::kHTMLDocumentInternalFieldCount); + ASSERT(result->InternalFieldCount() == V8HTMLDocument::internalFieldCount); v8::Local<v8::Object> marker = v8::Object::New(); - result->SetInternalField(V8Custom::kHTMLDocumentMarkerIndex, marker); - result->SetInternalField(V8Custom::kHTMLDocumentShadowIndex, marker); + result->SetInternalField(V8HTMLDocument::markerIndex, marker); + result->SetInternalField(V8HTMLDocument::shadowIndex, marker); } } @@ -1514,6 +1529,12 @@ v8::Handle<v8::Value> V8DOMWrapper::convertEventTargetToV8Object(EventTarget* ta return convertToV8Object(V8ClassIndex::DOMAPPLICATIONCACHE, domAppCache); #endif +#if ENABLE(EVENTSOURCE) + EventSource* eventSource = target->toEventSource(); + if (eventSource) + return convertToV8Object(V8ClassIndex::EVENTSOURCE, eventSource); +#endif + ASSERT(0); return notHandledByInterceptor(); } @@ -1578,6 +1599,22 @@ PassRefPtr<EventListener> V8DOMWrapper::getEventListener(XMLHttpRequestUpload* u return getEventListener(upload->associatedXMLHttpRequest(), value, isAttribute, lookup); } +#if ENABLE(EVENTSOURCE) +PassRefPtr<EventListener> V8DOMWrapper::getEventListener(EventSource* eventSource, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) +{ + if (V8Proxy::retrieve(eventSource->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; +} +#endif + PassRefPtr<EventListener> V8DOMWrapper::getEventListener(EventTarget* eventTarget, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) { if (V8Proxy::retrieve(eventTarget->scriptExecutionContext())) @@ -1632,7 +1669,7 @@ v8::Handle<v8::Value> V8DOMWrapper::convertStyleSheetToV8Object(StyleSheet* shee Node* ownerNode = sheet->ownerNode(); if (ownerNode) { v8::Handle<v8::Object> owner = v8::Handle<v8::Object>::Cast(convertNodeToV8Object(ownerNode)); - result->SetInternalField(V8Custom::kStyleSheetOwnerNodeIndex, owner); + result->SetInternalField(V8StyleSheet::ownerNodeIndex, owner); } return result; @@ -1737,7 +1774,7 @@ v8::Handle<v8::Value> V8DOMWrapper::convertWindowToV8Object(DOMWindow* window) if (!frame) return v8::Handle<v8::Object>(); - // Special case: Because of evaluateInNewContext() one DOMWindow can have + // Special case: Because of evaluateInIsolatedWorld() one DOMWindow can have // multiple contexts and multiple global objects associated with it. When // code running in one of those contexts accesses the window object, we // want to return the global object associated with that context, not @@ -1746,7 +1783,7 @@ v8::Handle<v8::Value> V8DOMWrapper::convertWindowToV8Object(DOMWindow* window) v8::Handle<v8::Object> currentGlobal = currentContext->Global(); v8::Handle<v8::Object> windowWrapper = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, currentGlobal); if (!windowWrapper.IsEmpty()) { - if (convertDOMWrapperToNative<DOMWindow>(windowWrapper) == window) + if (V8DOMWindow::toNative(windowWrapper) == window) return currentGlobal; } @@ -1780,7 +1817,7 @@ v8::Handle<v8::Value> V8DOMWrapper::convertNamedNodeMapToV8Object(NamedNodeMap* // Add a hidden reference from named node map to its owner node. if (Element* element = map->element()) { v8::Handle<v8::Object> owner = v8::Handle<v8::Object>::Cast(convertNodeToV8Object(element)); - result->SetInternalField(V8Custom::kNamedNodeMapOwnerNodeIndex, owner); + result->SetInternalField(V8NamedNodeMap::ownerNodeIndex, owner); } return result; diff --git a/WebCore/bindings/v8/V8DOMWrapper.h b/WebCore/bindings/v8/V8DOMWrapper.h index b00915e..3cff691 100644 --- a/WebCore/bindings/v8/V8DOMWrapper.h +++ b/WebCore/bindings/v8/V8DOMWrapper.h @@ -39,6 +39,7 @@ #include "V8CustomBinding.h" #include "V8CustomXPathNSResolver.h" #include "V8DOMMap.h" +#include "V8Event.h" #include "V8Index.h" #include "V8Utilities.h" #include "V8XPathNSResolver.h" @@ -91,6 +92,7 @@ namespace WebCore { class StyleSheetList; class V8EventListener; class V8ObjectEventListener; + class V8Proxy; #if ENABLE(WEB_SOCKETS) class WebSocket; #endif @@ -112,8 +114,8 @@ namespace WebCore { static void setDOMWrapper(v8::Handle<v8::Object> object, int type, void* cptr) { ASSERT(object->InternalFieldCount() >= 2); - object->SetPointerInInternalField(V8Custom::kDOMWrapperObjectIndex, cptr); - object->SetInternalField(V8Custom::kDOMWrapperTypeIndex, v8::Integer::New(type)); + object->SetPointerInInternalField(v8DOMWrapperObjectIndex, cptr); + object->SetInternalField(v8DOMWrapperTypeIndex, v8::Integer::New(type)); } static v8::Handle<v8::Object> lookupDOMWrapper(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Object> object) @@ -121,23 +123,6 @@ namespace WebCore { return object.IsEmpty() ? object : object->FindInstanceInPrototypeChain(getTemplate(type)); } - // A helper function extract native object pointer from a DOM wrapper - // and cast to the specified type. - template <class C> - static C* convertDOMWrapperToNative(v8::Handle<v8::Object> object) - { - ASSERT(maybeDOMWrapper(object)); - return reinterpret_cast<C*>(object->GetPointerFromInternalField(V8Custom::kDOMWrapperObjectIndex)); - } - - template <class C> - static C* convertDOMWrapperToNode(v8::Handle<v8::Object> object) - { - ASSERT(maybeDOMWrapper(object)); - ASSERT(domWrapperType(object) == V8ClassIndex::NODE); - return convertDOMWrapperToNative<C>(object); - } - template<typename T> static v8::Handle<v8::Value> convertToV8Object(V8ClassIndex::V8WrapperType type, PassRefPtr<T> imp) { @@ -166,31 +151,7 @@ namespace WebCore { return convertNewNodeToV8Object(node, 0, getDOMNodeMap()); } - static v8::Handle<v8::Value> convertNewNodeToV8Object(Node*, V8Proxy*, DOMWrapperMap<Node>&); - - template <class C> - static C* convertToNativeObject(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Object> object) - { - // Native event listener is per frame, it cannot be handled by this generic function. - ASSERT(type != V8ClassIndex::EVENTLISTENER); - ASSERT(type != V8ClassIndex::EVENTTARGET); - - ASSERT(maybeDOMWrapper(object)); - -#ifndef NDEBUG - const bool typeIsValid = -#define MAKE_CASE(TYPE, NAME) (type != V8ClassIndex::TYPE) && - DOM_NODE_TYPES(MAKE_CASE) -#if ENABLE(SVG) - SVG_NODE_TYPES(MAKE_CASE) -#endif -#undef MAKE_CASE - true; - ASSERT(typeIsValid); -#endif - - return convertDOMWrapperToNative<C>(object); - } + static v8::Handle<v8::Value> convertNewNodeToV8Object(Node*, V8Proxy*, DOMNodeMapping&); static V8ClassIndex::V8WrapperType domWrapperType(v8::Handle<v8::Object>); @@ -201,13 +162,6 @@ namespace WebCore { static v8::Handle<v8::Value> convertEventToV8Object(Event*); - static Event* convertToNativeEvent(v8::Handle<v8::Value> jsEvent) - { - if (!isDOMEventWrapper(jsEvent)) - return 0; - return convertDOMWrapperToNative<Event>(v8::Handle<v8::Object>::Cast(jsEvent)); - } - static v8::Handle<v8::Value> convertEventTargetToV8Object(PassRefPtr<EventTarget> eventTarget) { return convertEventTargetToV8Object(eventTarget.get()); @@ -237,6 +191,10 @@ namespace WebCore { 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); @@ -247,7 +205,7 @@ namespace WebCore { { RefPtr<XPathNSResolver> resolver; if (V8XPathNSResolver::HasInstance(value)) - resolver = convertToNativeObject<XPathNSResolver>(V8ClassIndex::XPATHNSRESOLVER, v8::Handle<v8::Object>::Cast(value)); + resolver = V8XPathNSResolver::toNative(v8::Handle<v8::Object>::Cast(value)); else if (value->IsObject()) resolver = V8CustomXPathNSResolver::create(proxy, value->ToObject()); return resolver; @@ -267,12 +225,6 @@ namespace WebCore { static v8::Local<v8::Function> getConstructor(V8ClassIndex::V8WrapperType, DOMWindow*); static v8::Local<v8::Function> getConstructor(V8ClassIndex::V8WrapperType, WorkerContext*); - // Checks whether a DOM object has a JS wrapper. - static bool domObjectHasJSWrapper(void*); - // Get JS wrapper of an existing DOM object, assuming that the wrapper - // exists. - static v8::Persistent<v8::Object> jsWrapperForDOMObject(void*); - static v8::Persistent<v8::Object> jsWrapperForActiveDOMObject(void*); // Set JS wrapper of a DOM object, the caller in charge of increase ref. static void setJSWrapperForDOMObject(void*, v8::Persistent<v8::Object>); static void setJSWrapperForActiveDOMObject(void*, v8::Persistent<v8::Object>); @@ -281,8 +233,6 @@ namespace WebCore { // Check whether a V8 value is a wrapper of type |classType|. static bool isWrapperOfType(v8::Handle<v8::Value>, V8ClassIndex::V8WrapperType); - static void* convertToSVGPODTypeImpl(V8ClassIndex::V8WrapperType, v8::Handle<v8::Value>); - // Check whether a V8 value is a DOM Event wrapper. static bool isDOMEventWrapper(v8::Handle<v8::Value>); diff --git a/WebCore/bindings/v8/V8HiddenPropertyName.h b/WebCore/bindings/v8/V8HiddenPropertyName.h index bb1ca4c..0bfadd9 100644 --- a/WebCore/bindings/v8/V8HiddenPropertyName.h +++ b/WebCore/bindings/v8/V8HiddenPropertyName.h @@ -39,6 +39,7 @@ namespace WebCore { V(objectPrototype) \ V(listener) \ V(attributeListener) \ + V(scriptState) \ V(sleepFunction) \ V(toStringString) diff --git a/WebCore/bindings/v8/V8Index.cpp b/WebCore/bindings/v8/V8Index.cpp index ea13d2f..b87e060 100644 --- a/WebCore/bindings/v8/V8Index.cpp +++ b/WebCore/bindings/v8/V8Index.cpp @@ -34,6 +34,7 @@ #include "V8Attr.h" #include "V8BarInfo.h" #include "V8BeforeLoadEvent.h" +#include "V8Blob.h" #include "V8WebGLActiveInfo.h" #include "V8CanvasRenderingContext.h" #include "V8CanvasRenderingContext2D.h" @@ -154,6 +155,7 @@ #include "V8NodeList.h" #include "V8NodeFilter.h" #include "V8Notation.h" +#include "V8PopStateEvent.h" #include "V8ProcessingInstruction.h" #include "V8ProgressEvent.h" #include "V8StyleSheet.h" @@ -249,11 +251,13 @@ #endif #if ENABLE(SVG_FONTS) +#include "V8SVGFontElement.h" #include "V8SVGFontFaceElement.h" #include "V8SVGFontFaceFormatElement.h" #include "V8SVGFontFaceNameElement.h" #include "V8SVGFontFaceSrcElement.h" #include "V8SVGFontFaceUriElement.h" +#include "V8SVGMissingGlyphElement.h" #endif #if ENABLE(SVG_FOREIGN_OBJECT) @@ -400,6 +404,7 @@ #include "V8WebGLArray.h" #include "V8WebGLByteArray.h" #include "V8WebGLBuffer.h" +#include "V8WebGLContextAttributes.h" #include "V8WebGLFloatArray.h" #include "V8WebGLFramebuffer.h" #include "V8WebGLIntArray.h" @@ -422,6 +427,13 @@ #include "V8SQLTransaction.h" #endif +#if ENABLE(INDEXED_DATABASE) +#include "V8IDBDatabaseError.h" +#include "V8IDBDatabaseException.h" +#include "V8IDBRequest.h" +#include "V8IndexedDatabaseRequest.h" +#endif + #if ENABLE(XPATH) #include "V8XPathResult.h" #include "V8XPathException.h" @@ -440,6 +452,10 @@ #include "V8InspectorFrontendHost.h" #endif +#if ENABLE(EVENTSOURCE) +#include "V8EventSource.h" +#endif + // Geolocation #include "V8Coordinates.h" #include "V8Geolocation.h" diff --git a/WebCore/bindings/v8/V8Index.h b/WebCore/bindings/v8/V8Index.h index a3aebdf..f7582f7 100644 --- a/WebCore/bindings/v8/V8Index.h +++ b/WebCore/bindings/v8/V8Index.h @@ -32,10 +32,13 @@ #define V8Index_h #include <v8.h> -#include "PlatformString.h" // for WebCore::String namespace WebCore { +static const int v8DOMWrapperTypeIndex = 0; +static const int v8DOMWrapperObjectIndex = 1; +static const int v8DefaultWrapperInternalFieldCount = 2; + typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); #if ENABLE(DATAGRID) @@ -82,6 +85,13 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); #define WORKER_NONNODE_WRAPPER_TYPES(V) #endif +#if ENABLE(EVENTSOURCE) +#define EVENTSOURCE_ACTIVE_OBJECT_WRAPPER_TYPES(V) \ + V(EVENTSOURCE, EventSource) +#else +#define EVENTSOURCE_ACTIVE_OBJECT_WRAPPER_TYPES(V) +#endif + #if ENABLE(OFFLINE_WEB_APPLICATIONS) #define APPLICATIONCACHE_NONNODE_WRAPPER_TYPES(V) \ V(DOMAPPLICATIONCACHE, DOMApplicationCache) @@ -230,11 +240,13 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); #if ENABLE(SVG_FONTS) #define SVG_FONTS_ELEMENT_TYPES(V) \ + V(SVGFONTELEMENT, SVGFontElement) \ V(SVGFONTFACEELEMENT, SVGFontFaceElement) \ V(SVGFONTFACEFORMATELEMENT, SVGFontFaceFormatElement) \ V(SVGFONTFACENAMEELEMENT, SVGFontFaceNameElement) \ V(SVGFONTFACESRCELEMENT, SVGFontFaceSrcElement) \ - V(SVGFONTFACEURIELEMENT, SVGFontFaceUriElement) + V(SVGFONTFACEURIELEMENT, SVGFontFaceUriElement) \ + V(SVGMISSINGGLYPHELEMENT, SVGMissingGlyphElement) #else #define SVG_FONTS_ELEMENT_TYPES(V) #endif @@ -316,7 +328,8 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); V(XMLHTTPREQUEST, XMLHttpRequest) \ WORKER_ACTIVE_OBJECT_WRAPPER_TYPES(V) \ SHARED_WORKER_ACTIVE_OBJECT_WRAPPER_TYPES(V) \ - WEBSOCKET_ACTIVE_OBJECT_WRAPPER_TYPES(V) + WEBSOCKET_ACTIVE_OBJECT_WRAPPER_TYPES(V) \ + EVENTSOURCE_ACTIVE_OBJECT_WRAPPER_TYPES(V) // NOTE: DOM_OBJECT_TYPES is split into two halves because // Visual Studio's Intellinonsense crashes when macros get @@ -325,6 +338,7 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); #define DOM_OBJECT_TYPES_1(V) \ V(BARINFO, BarInfo) \ V(BEFORELOADEVENT, BeforeLoadEvent) \ + V(BLOB, Blob) \ V(CANVASGRADIENT, CanvasGradient) \ V(CANVASPATTERN, CanvasPattern) \ V(CANVASRENDERINGCONTEXT, CanvasRenderingContext) \ @@ -386,6 +400,7 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); V(PAGETRANSITIONEVENT, PageTransitionEvent) \ V(PLUGIN, Plugin) \ V(PLUGINARRAY, PluginArray) \ + V(POPSTATEEVENT, PopStateEvent) \ V(PROGRESSEVENT, ProgressEvent) \ V(RANGE, Range) \ V(RANGEEXCEPTION, RangeException) \ @@ -438,6 +453,16 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); #define DOM_OBJECT_STORAGE_TYPES(V) #endif +#if ENABLE(INDEXED_DATABASE) +#define DOM_OBJECT_INDEXED_DATABASE_TYPES(V) \ + V(IDBDATABASEERROR, IDBDatabaseError) \ + V(IDBDATABASEEXCEPTION, IDBDatabaseException) \ + V(IDBREQUEST, IDBRequest) \ + V(INDEXEDDATABASEREQUEST, IndexedDatabaseRequest) +#else +#define DOM_OBJECT_INDEXED_DATABASE_TYPES(V) +#endif + #if ENABLE(WORKERS) #define DOM_OBJECT_WORKERS_TYPES(V) \ V(ERROREVENT, ErrorEvent) @@ -452,6 +477,7 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); V(WEBGLARRAYBUFFER, WebGLArrayBuffer) \ V(WEBGLBUFFER, WebGLBuffer) \ V(WEBGLBYTEARRAY, WebGLByteArray) \ + V(WEBGLCONTEXTATTRIBUTES, WebGLContextAttributes) \ V(WEBGLFLOATARRAY, WebGLFloatArray) \ V(WEBGLFRAMEBUFFER, WebGLFramebuffer) \ V(WEBGLINTARRAY, WebGLIntArray) \ @@ -530,6 +556,7 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); DOM_OBJECT_TYPES_2(V) \ DOM_OBJECT_DATABASE_TYPES(V) \ DOM_OBJECT_STORAGE_TYPES(V) \ + DOM_OBJECT_INDEXED_DATABASE_TYPES(V) \ DOM_OBJECT_WORKERS_TYPES(V) \ DOM_OBJECT_3D_CANVAS_TYPES(V) \ DOM_OBJECT_XPATH_TYPES(V) \ @@ -544,7 +571,6 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); #if ENABLE(SVG) // SVG_OBJECT_TYPES are svg non-node, non-pod types. #define SVG_OBJECT_TYPES(V) \ - V(SVGANGLE, SVGAngle) \ V(SVGANIMATEDANGLE, SVGAnimatedAngle) \ V(SVGANIMATEDBOOLEAN, SVGAnimatedBoolean) \ V(SVGANIMATEDENUMERATION, SVGAnimatedEnumeration) \ @@ -586,7 +612,6 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); V(SVGPATHSEGMOVETOABS, SVGPathSegMovetoAbs) \ V(SVGPATHSEGMOVETOREL, SVGPathSegMovetoRel) \ V(SVGPOINTLIST, SVGPointList) \ - V(SVGPRESERVEASPECTRATIO, SVGPreserveAspectRatio) \ V(SVGRENDERINGINTENT, SVGRenderingIntent) \ V(SVGSTRINGLIST, SVGStringList) \ V(SVGTRANSFORMLIST, SVGTransformList) \ @@ -595,7 +620,9 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); // SVG POD types should list all types whose IDL has PODType declaration. #define SVG_POD_TYPES(V) \ + V(SVGANGLE, SVGAngle) \ V(SVGLENGTH, SVGLength) \ + V(SVGPRESERVEASPECTRATIO, SVGPreserveAspectRatio) \ V(SVGTRANSFORM, SVGTransform) \ V(SVGMATRIX, SVGMatrix) \ V(SVGNUMBER, SVGNumber) \ @@ -604,7 +631,9 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); // POD types can have different implementation names, see CodeGenerateV8.pm. #define SVG_POD_NATIVE_TYPES(V) \ + V(SVGANGLE, SVGAngle) \ V(SVGLENGTH, SVGLength) \ + V(SVGPRESERVEASPECTRATIO, SVGPreserveAspectRatio) \ V(SVGTRANSFORM, SVGTransform) \ V(SVGMATRIX, TransformationMatrix) \ V(SVGNUMBER, float) \ diff --git a/WebCore/bindings/v8/V8IsolatedWorld.cpp b/WebCore/bindings/v8/V8IsolatedContext.cpp index cb65097..3237ede 100644 --- a/WebCore/bindings/v8/V8IsolatedWorld.cpp +++ b/WebCore/bindings/v8/V8IsolatedContext.cpp @@ -30,9 +30,7 @@ #include "config.h" -#include "V8IsolatedWorld.h" - -#include <v8.h> +#include "V8IsolatedContext.h" #include "Frame.h" #include "FrameLoaderClient.h" @@ -40,34 +38,35 @@ #include "ScriptController.h" #include "V8DOMWindow.h" #include "V8HiddenPropertyName.h" +#include <v8.h> namespace WebCore { -int V8IsolatedWorld::isolatedWorldCount = 0; -void V8IsolatedWorld::contextWeakReferenceCallback(v8::Persistent<v8::Value> object, void* isolated_world) +void V8IsolatedContext::contextWeakReferenceCallback(v8::Persistent<v8::Value> object, void* isolatedContext) { // Our context is going away. Time to clean up the world. - V8IsolatedWorld* world = static_cast<V8IsolatedWorld*>(isolated_world); - delete world; + V8IsolatedContext* context = static_cast<V8IsolatedContext*>(isolatedContext); + delete context; } -V8IsolatedWorld::V8IsolatedWorld(V8Proxy* proxy, int extensionGroup) +V8IsolatedContext::V8IsolatedContext(V8Proxy* proxy, int extensionGroup) + : m_world(IsolatedWorld::create()) { - ++isolatedWorldCount; - v8::HandleScope scope; - m_context = SharedPersistent<v8::Context>::create(proxy->createNewContext(v8::Handle<v8::Object>(), extensionGroup)); + // FIXME: We should be creating a new V8DOMWindowShell here instead of riping out the context. + m_context = SharedPersistent<v8::Context>::create(proxy->windowShell()->createNewContext(v8::Handle<v8::Object>(), extensionGroup)); if (m_context->get().IsEmpty()) return; // Run code in the new context. - v8::Context::Scope context_scope(m_context->get()); + v8::Context::Scope contextScope(m_context->get()); - getGlobalObject(m_context->get())->SetPointerInInternalField(V8Custom::kDOMWindowEnteredIsolatedWorldIndex, this); + getGlobalObject(m_context->get())->SetPointerInInternalField(V8DOMWindow::enteredIsolatedWorldIndex, this); - V8Proxy::installHiddenObjectPrototype(m_context->get()); - proxy->installDOMWindow(m_context->get(), proxy->frame()->domWindow()); + V8DOMWindowShell::installHiddenObjectPrototype(m_context->get()); + // FIXME: This will go away once we have a windowShell for the isolated world. + proxy->windowShell()->installDOMWindow(m_context->get(), proxy->frame()->domWindow()); // Using the default security token means that the canAccess is always // called, which is slow. @@ -80,14 +79,13 @@ V8IsolatedWorld::V8IsolatedWorld(V8Proxy* proxy, int extensionGroup) proxy->frame()->loader()->client()->didCreateIsolatedScriptContext(); } -void V8IsolatedWorld::destroy() +void V8IsolatedContext::destroy() { m_context->get().MakeWeak(this, &contextWeakReferenceCallback); } -V8IsolatedWorld::~V8IsolatedWorld() +V8IsolatedContext::~V8IsolatedContext() { - --isolatedWorldCount; m_context->disposeHandle(); } diff --git a/WebCore/bindings/v8/V8IsolatedContext.h b/WebCore/bindings/v8/V8IsolatedContext.h new file mode 100644 index 0000000..70ca270 --- /dev/null +++ b/WebCore/bindings/v8/V8IsolatedContext.h @@ -0,0 +1,116 @@ +/* + * 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. + */ + +#ifndef V8IsolatedContext_h +#define V8IsolatedContext_h + +#include "IsolatedWorld.h" +#include "ScriptSourceCode.h" // for WebCore::ScriptSourceCode +#include "V8DOMWindow.h" +#include "V8Index.h" +#include "V8Proxy.h" +#include "V8Utilities.h" +#include <v8.h> + +namespace WebCore { + +class V8Proxy; + +// V8IsolatedContext +// +// V8IsolatedContext represents a isolated execution environment for +// JavaScript. Each isolated world executes in parallel with the main +// JavaScript world. An isolated world has access to the same DOM data +// structures as the main world but none of the JavaScript pointers. +// +// It is an error to ever share a JavaScript pointer between two isolated +// worlds or between an isolated world and the main world. Because +// isolated worlds have access to the DOM, they need their own DOM wrappers +// to avoid having pointers to the main world's DOM wrappers (which are +// JavaScript objects). +class V8IsolatedContext { +public: + // Creates an isolated world. To destroy it, call destroy(). + // This will delete the isolated world when the context it owns is GC'd. + V8IsolatedContext(V8Proxy* proxy, int extensionGroup); + ~V8IsolatedContext(); + + // Call this to destroy the isolated world. It will be deleted sometime + // after this call, once all script references to the world's context + // have been dropped. + void destroy(); + + // Returns the isolated world associated with + // v8::Context::GetEntered(). Because worlds are isolated, the entire + // JavaScript call stack should be from the same isolated world. + // Returns 0 if the entered context is from the main world. + // + // FIXME: Consider edge cases with DOM mutation events that might + // violate this invariant. + // + static V8IsolatedContext* getEntered() + { + // This is a temporary performance optimization. Essentially, + // GetHiddenValue is too slow for this code path. We need to get the + // V8 team to add a real property to v8::Context for isolated worlds. + // Until then, we optimize the common case of not having any isolated + // worlds at all. + if (!IsolatedWorld::count()) + return 0; + if (!v8::Context::InContext()) + return 0; + return reinterpret_cast<V8IsolatedContext*>(getGlobalObject(v8::Context::GetEntered())->GetPointerFromInternalField(V8DOMWindow::enteredIsolatedWorldIndex)); + } + + v8::Handle<v8::Context> context() { return m_context->get(); } + PassRefPtr<SharedPersistent<v8::Context> > sharedContext() { return m_context; } + + IsolatedWorld* world() const { return m_world.get(); } + +private: + static v8::Handle<v8::Object> getGlobalObject(v8::Handle<v8::Context> context) + { + return v8::Handle<v8::Object>::Cast(context->Global()->GetPrototype()); + } + + // Called by the garbage collector when our JavaScript context is about + // to be destroyed. + static void contextWeakReferenceCallback(v8::Persistent<v8::Value> object, void* isolatedContext); + + // The underlying v8::Context. This object is keep on the heap as + // long as |m_context| has not been garbage collected. + RefPtr<SharedPersistent<v8::Context> > m_context; + + RefPtr<IsolatedWorld> m_world; +}; + +} // namespace WebCore + +#endif // V8IsolatedContext_h diff --git a/WebCore/bindings/v8/V8IsolatedWorld.h b/WebCore/bindings/v8/V8IsolatedWorld.h deleted file mode 100644 index 6313da8..0000000 --- a/WebCore/bindings/v8/V8IsolatedWorld.h +++ /dev/null @@ -1,122 +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. - */ - -#ifndef V8IsolatedWorld_h -#define V8IsolatedWorld_h - -#include <v8.h> - -#include "V8DOMMap.h" -#include "V8Index.h" -#include "V8Proxy.h" -#include "V8Utilities.h" -#include "ScriptSourceCode.h" // for WebCore::ScriptSourceCode - -namespace WebCore { - - class V8Proxy; - - // V8IsolatedWorld - // - // V8IsolatedWorld represents a isolated execution environment for - // JavaScript. Each isolated world executes in parallel with the main - // JavaScript world. An isolated world has access to the same DOM data - // structures as the main world but none of the JavaScript pointers. - // - // It is an error to ever share a JavaScript pointer between two isolated - // worlds or between an isolated world and the main world. Because - // isolated worlds have access to the DOM, they need their own DOM wrappers - // to avoid having pointers to the main world's DOM wrappers (which are - // JavaScript objects). - // - class V8IsolatedWorld { - public: - // Creates an isolated world. To destroy it, call destroy(). - // This will delete the isolated world when the context it owns is GC'd. - V8IsolatedWorld(V8Proxy* proxy, int extensionGroup); - ~V8IsolatedWorld(); - - // Call this to destroy the isolated world. It will be deleted sometime - // after this call, once all script references to the world's context - // have been dropped. - void destroy(); - - // Returns the isolated world associated with - // v8::Context::GetEntered(). Because worlds are isolated, the entire - // JavaScript call stack should be from the same isolated world. - // Returns NULL if the entered context is from the main world. - // - // FIXME: Consider edge cases with DOM mutation events that might - // violate this invariant. - // - static V8IsolatedWorld* getEntered() - { - // This is a temporary performance optimization. Essentially, - // GetHiddenValue is too slow for this code path. We need to get the - // V8 team to add a real property to v8::Context for isolated worlds. - // Until then, we optimize the common case of not having any isolated - // worlds at all. - if (!isolatedWorldCount) - return 0; - if (!v8::Context::InContext()) - return 0; - return reinterpret_cast<V8IsolatedWorld*>(getGlobalObject(v8::Context::GetEntered())->GetPointerFromInternalField(V8Custom::kDOMWindowEnteredIsolatedWorldIndex)); - } - - v8::Handle<v8::Context> context() { return m_context->get(); } - PassRefPtr<SharedPersistent<v8::Context> > sharedContext() { return m_context; } - - DOMDataStore* getDOMDataStore() const { return m_domDataStore.getStore(); } - - private: - static v8::Handle<v8::Object> getGlobalObject(v8::Handle<v8::Context> context) - { - return v8::Handle<v8::Object>::Cast(context->Global()->GetPrototype()); - } - - // Called by the garbage collector when our JavaScript context is about - // to be destroyed. - static void contextWeakReferenceCallback(v8::Persistent<v8::Value> object, void* isolated_world); - - // The v8::Context for the isolated world. This object is keep on the - // heap as long as |m_context| has not been garbage collected. - RefPtr<SharedPersistent<v8::Context> > m_context; - - // The backing store for the isolated world's DOM wrappers. This class - // doesn't have visibility into the wrappers. This handle simply helps - // manage their lifetime. - DOMDataStoreHandle m_domDataStore; - - static int isolatedWorldCount; - }; - -} // namespace WebCore - -#endif // V8IsolatedWorld_h diff --git a/WebCore/bindings/v8/V8LazyEventListener.cpp b/WebCore/bindings/v8/V8LazyEventListener.cpp index 16b21d6..7f13c5a 100644 --- a/WebCore/bindings/v8/V8LazyEventListener.cpp +++ b/WebCore/bindings/v8/V8LazyEventListener.cpp @@ -54,7 +54,11 @@ V8LazyEventListener::V8LazyEventListener(const String& functionName, bool isSVGE v8::Local<v8::Value> V8LazyEventListener::callListenerFunction(ScriptExecutionContext* context, v8::Handle<v8::Value> jsEvent, Event* event) { - v8::Local<v8::Function> handlerFunction = v8::Local<v8::Function>::Cast(getListenerObject(context)); + v8::Local<v8::Object> listenerObject = getListenerObject(context); + if (listenerObject.IsEmpty()) + return v8::Local<v8::Value>(); + + v8::Local<v8::Function> handlerFunction = v8::Local<v8::Function>::Cast(listenerObject); v8::Local<v8::Object> receiver = getReceiverObject(event); if (handlerFunction.IsEmpty() || receiver.IsEmpty()) return v8::Local<v8::Value>(); diff --git a/WebCore/bindings/v8/V8NPObject.cpp b/WebCore/bindings/v8/V8NPObject.cpp index bab3688..196972e 100644 --- a/WebCore/bindings/v8/V8NPObject.cpp +++ b/WebCore/bindings/v8/V8NPObject.cpp @@ -65,19 +65,25 @@ static v8::Handle<v8::Value> npObjectInvokeImpl(const v8::Arguments& args, Invok if (V8HTMLAppletElement::HasInstance(args.Holder()) || V8HTMLEmbedElement::HasInstance(args.Holder()) || V8HTMLObjectElement::HasInstance(args.Holder())) { // The holder object is a subtype of HTMLPlugInElement. - HTMLPlugInElement* element = V8DOMWrapper::convertDOMWrapperToNode<HTMLPlugInElement>(args.Holder()); + HTMLPlugInElement* element; + if (V8HTMLAppletElement::HasInstance(args.Holder())) + element = V8HTMLAppletElement::toNative(args.Holder()); + else if (V8HTMLEmbedElement::HasInstance(args.Holder())) + element = V8HTMLEmbedElement::toNative(args.Holder()); + else + element = V8HTMLObjectElement::toNative(args.Holder()); ScriptInstance scriptInstance = element->getInstance(); if (scriptInstance) - npObject = V8DOMWrapper::convertToNativeObject<NPObject>(V8ClassIndex::NPOBJECT, scriptInstance->instance()); + npObject = v8ObjectToNPObject(scriptInstance->instance()); else npObject = 0; } else { // The holder object is not a subtype of HTMLPlugInElement, it must be an NPObject which has three // internal fields. - if (args.Holder()->InternalFieldCount() != V8Custom::kNPObjectInternalFieldCount) + if (args.Holder()->InternalFieldCount() != npObjectInternalFieldCount) return throwError("NPMethod called on non-NPObject", V8Proxy::ReferenceError); - npObject = V8DOMWrapper::convertToNativeObject<NPObject>(V8ClassIndex::NPOBJECT, args.Holder()); + npObject = v8ObjectToNPObject(args.Holder()); } // Verify that our wrapper wasn't using a NPObject which has already been deleted. @@ -161,7 +167,7 @@ static void weakTemplateCallback(v8::Persistent<v8::Value> object, void* paramet static v8::Handle<v8::Value> npObjectGetProperty(v8::Local<v8::Object> self, NPIdentifier identifier, v8::Local<v8::Value> key) { - NPObject* npObject = V8DOMWrapper::convertToNativeObject<NPObject>(V8ClassIndex::NPOBJECT, self); + NPObject* npObject = v8ObjectToNPObject(self); // Verify that our wrapper wasn't using a NPObject which // has already been deleted. @@ -230,7 +236,7 @@ v8::Handle<v8::Value> npObjectGetIndexedProperty(v8::Local<v8::Object> self, uin static v8::Handle<v8::Value> npObjectSetProperty(v8::Local<v8::Object> self, NPIdentifier identifier, v8::Local<v8::Value> value) { - NPObject* npObject = V8DOMWrapper::convertToNativeObject<NPObject>(V8ClassIndex::NPOBJECT, self); + NPObject* npObject = v8ObjectToNPObject(self); // Verify that our wrapper wasn't using a NPObject which has already been deleted. if (!npObject || !_NPN_IsAlive(npObject)) { @@ -280,7 +286,7 @@ v8::Handle<v8::Value> npObjectSetIndexedProperty(v8::Local<v8::Object> self, uin v8::Handle<v8::Array> npObjectPropertyEnumerator(const v8::AccessorInfo& info, bool namedProperty) { - NPObject* npObject = V8DOMWrapper::convertToNativeObject<NPObject>(V8ClassIndex::NPOBJECT, info.Holder()); + NPObject* npObject = v8ObjectToNPObject(info.Holder()); // Verify that our wrapper wasn't using a NPObject which // has already been deleted. @@ -357,7 +363,7 @@ v8::Local<v8::Object> createV8ObjectForNPObject(NPObject* object, NPObject* root // can be used by DOM bindings. if (npObjectDesc.IsEmpty()) { npObjectDesc = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New()); - npObjectDesc->InstanceTemplate()->SetInternalFieldCount(V8Custom::kNPObjectInternalFieldCount); + npObjectDesc->InstanceTemplate()->SetInternalFieldCount(npObjectInternalFieldCount); npObjectDesc->InstanceTemplate()->SetNamedPropertyHandler(npObjectNamedPropertyGetter, npObjectNamedPropertySetter, 0, 0, npObjectNamedPropertyEnumerator); npObjectDesc->InstanceTemplate()->SetIndexedPropertyHandler(npObjectIndexedPropertyGetter, npObjectIndexedPropertySetter, 0, 0, npObjectIndexedPropertyEnumerator); npObjectDesc->InstanceTemplate()->SetCallAsFunctionHandler(npObjectInvokeDefaultHandler); diff --git a/WebCore/bindings/v8/V8Proxy.cpp b/WebCore/bindings/v8/V8Proxy.cpp index 5da73d5..a5cc433 100644 --- a/WebCore/bindings/v8/V8Proxy.cpp +++ b/WebCore/bindings/v8/V8Proxy.cpp @@ -42,6 +42,7 @@ #include "ScriptController.h" #include "StorageNamespace.h" #include "V8Binding.h" +#include "V8BindingState.h" #include "V8Collection.h" #include "V8ConsoleMessage.h" #include "V8CustomBinding.h" @@ -49,7 +50,7 @@ #include "V8DOMWindow.h" #include "V8HiddenPropertyName.h" #include "V8Index.h" -#include "V8IsolatedWorld.h" +#include "V8IsolatedContext.h" #include "WorkerContextExecutionProxy.h" #include <algorithm> @@ -174,7 +175,7 @@ enum DelayReporting { ReportNow }; -static void reportUnsafeAccessTo(Frame* target, DelayReporting delay) +void V8Proxy::reportUnsafeAccessTo(Frame* target, DelayReporting delay) { ASSERT(target); Document* targetDocument = target->document(); @@ -214,13 +215,6 @@ static void reportUnsafeAccessTo(Frame* target, DelayReporting delay) } } -static void reportUnsafeJavaScriptAccess(v8::Local<v8::Object> host, v8::AccessType type, v8::Local<v8::Value> data) -{ - Frame* target = V8Custom::GetTargetFrame(host, data); - if (target) - reportUnsafeAccessTo(target, ReportLater); -} - static void handleFatalErrorInV8() { // FIXME: We temporarily deal with V8 internal error situations @@ -228,17 +222,9 @@ static void handleFatalErrorInV8() CRASH(); } -static void reportFatalErrorInV8(const char* location, const char* message) -{ - // V8 is shutdown, we cannot use V8 api. - // The only thing we can do is to disable JavaScript. - // FIXME: clean up V8Proxy and disable JavaScript. - printf("V8 error: %s (%s)\n", message, location); - handleFatalErrorInV8(); -} - V8Proxy::V8Proxy(Frame* frame) : m_frame(frame) + , m_windowShell(V8DOMWindowShell::create(frame)) , m_inlineCode(false) , m_timerCallback(false) , m_recursion(0) @@ -248,18 +234,7 @@ V8Proxy::V8Proxy(Frame* frame) V8Proxy::~V8Proxy() { clearForClose(); - destroyGlobal(); -} - -void V8Proxy::destroyGlobal() -{ - if (!m_global.IsEmpty()) { -#ifndef NDEBUG - V8GCController::unregisterGlobalHandle(this, m_global); -#endif - m_global.Dispose(); - m_global.Clear(); - } + windowShell()->destroyGlobal(); } v8::Handle<v8::Script> V8Proxy::compileScript(v8::Handle<v8::String> code, const String& fileName, int baseLine) @@ -297,7 +272,7 @@ bool V8Proxy::handleOutOfMemory() // Clean m_context, and event handlers. proxy->clearForClose(); - proxy->destroyGlobal(); + proxy->windowShell()->destroyGlobal(); } #if PLATFORM(CHROMIUM) @@ -315,104 +290,58 @@ bool V8Proxy::handleOutOfMemory() void V8Proxy::evaluateInIsolatedWorld(int worldID, const Vector<ScriptSourceCode>& sources, int extensionGroup) { - initContextIfNeeded(); + // FIXME: This will need to get reorganized once we have a windowShell for the isolated world. + windowShell()->initContextIfNeeded(); v8::HandleScope handleScope; - V8IsolatedWorld* world = 0; + V8IsolatedContext* isolatedContext = 0; if (worldID > 0) { IsolatedWorldMap::iterator iter = m_isolatedWorlds.find(worldID); if (iter != m_isolatedWorlds.end()) { - world = iter->second; + isolatedContext = iter->second; } else { - world = new V8IsolatedWorld(this, extensionGroup); - if (world->context().IsEmpty()) { - delete world; + isolatedContext = new V8IsolatedContext(this, extensionGroup); + if (isolatedContext->context().IsEmpty()) { + delete isolatedContext; return; } - m_isolatedWorlds.set(worldID, world); + // FIXME: We should change this to using window shells to match JSC. + m_isolatedWorlds.set(worldID, isolatedContext); // Setup context id for JS debugger. - if (!setInjectedScriptContextDebugId(world->context())) { + if (!setInjectedScriptContextDebugId(isolatedContext->context())) { m_isolatedWorlds.take(worldID); - delete world; + delete isolatedContext; return; } } } else { - world = new V8IsolatedWorld(this, extensionGroup); - if (world->context().IsEmpty()) { - delete world; + isolatedContext = new V8IsolatedContext(this, extensionGroup); + if (isolatedContext->context().IsEmpty()) { + delete isolatedContext; return; } } - v8::Local<v8::Context> context = v8::Local<v8::Context>::New(world->context()); + v8::Local<v8::Context> context = v8::Local<v8::Context>::New(isolatedContext->context()); v8::Context::Scope context_scope(context); for (size_t i = 0; i < sources.size(); ++i) evaluate(sources[i], 0); if (worldID == 0) - world->destroy(); -} - -void V8Proxy::evaluateInNewContext(const Vector<ScriptSourceCode>& sources, int extensionGroup) -{ - initContextIfNeeded(); - - v8::HandleScope handleScope; - - // Set up the DOM window as the prototype of the new global object. - v8::Handle<v8::Context> windowContext = m_context; - v8::Handle<v8::Object> windowGlobal = windowContext->Global(); - v8::Handle<v8::Object> windowWrapper = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, windowGlobal); - - ASSERT(V8DOMWrapper::convertDOMWrapperToNative<DOMWindow>(windowWrapper) == m_frame->domWindow()); - - v8::Persistent<v8::Context> context = createNewContext(v8::Handle<v8::Object>(), extensionGroup); - if (context.IsEmpty()) - return; - - v8::Context::Scope contextScope(context); - - // Setup context id for JS debugger. - if (!setInjectedScriptContextDebugId(context)) { - context.Dispose(); - return; - } - - v8::Handle<v8::Object> global = context->Global(); - - v8::Handle<v8::String> implicitProtoString = v8::String::New("__proto__"); - global->Set(implicitProtoString, windowWrapper); - - // Give the code running in the new context a way to get access to the - // original context. - global->Set(v8::String::New("contentWindow"), windowGlobal); - - m_frame->loader()->client()->didCreateIsolatedScriptContext(); - - // Run code in the new context. - for (size_t i = 0; i < sources.size(); ++i) - evaluate(sources[i], 0); - - // Using the default security token means that the canAccess is always - // called, which is slow. - // FIXME: Use tokens where possible. This will mean keeping track of all - // created contexts so that they can all be updated when the document domain - // changes. - context->UseDefaultSecurityToken(); - context.Dispose(); + isolatedContext->destroy(); } bool V8Proxy::setInjectedScriptContextDebugId(v8::Handle<v8::Context> targetContext) { // Setup context id for JS debugger. v8::Context::Scope contextScope(targetContext); - if (m_context.IsEmpty()) + v8::Handle<v8::Context> context = windowShell()->context(); + if (context.IsEmpty()) return false; - int debugId = contextDebugId(m_context); + int debugId = contextDebugId(context); char buffer[32]; if (debugId == -1) @@ -611,37 +540,13 @@ v8::Local<v8::Value> V8Proxy::newInstance(v8::Handle<v8::Function> constructor, return result; } -v8::Local<v8::Object> V8Proxy::createWrapperFromCacheSlowCase(V8ClassIndex::V8WrapperType 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); - return instance->Clone(); - } - return notHandledByInterceptor(); -} - -bool V8Proxy::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(); -} - DOMWindow* V8Proxy::retrieveWindow(v8::Handle<v8::Context> context) { v8::Handle<v8::Object> global = context->Global(); ASSERT(!global.IsEmpty()); global = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, global); ASSERT(!global.IsEmpty()); - return V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, global); + return V8DOMWindow::toNative(global); } Frame* V8Proxy::retrieveFrame(v8::Handle<v8::Context> context) @@ -691,12 +596,12 @@ V8Proxy* V8Proxy::retrieve(Frame* frame) { if (!frame) return 0; - return frame->script()->isEnabled() ? frame->script()->proxy() : 0; + return frame->script()->canExecuteScripts() ? frame->script()->proxy() : 0; } V8Proxy* V8Proxy::retrieve(ScriptExecutionContext* context) { - if (!context->isDocument()) + if (!context || !context->isDocument()) return 0; return retrieve(static_cast<Document*>(context)->frame()); } @@ -705,79 +610,6 @@ void V8Proxy::disconnectFrame() { } -void V8Proxy::updateDocumentWrapper(v8::Handle<v8::Value> wrapper) -{ - clearDocumentWrapper(); - - ASSERT(m_document.IsEmpty()); - m_document = v8::Persistent<v8::Value>::New(wrapper); -#ifndef NDEBUG - V8GCController::registerGlobalHandle(PROXY, this, m_document); -#endif -} - -void V8Proxy::clearDocumentWrapper() -{ - if (!m_document.IsEmpty()) { -#ifndef NDEBUG - V8GCController::unregisterGlobalHandle(this, m_document); -#endif - m_document.Dispose(); - m_document.Clear(); - } -} - -void V8Proxy::updateDocumentWrapperCache() -{ - v8::HandleScope handleScope; - v8::Context::Scope contextScope(m_context); - - // If the document has no frame, NodeToV8Object might get the - // document wrapper for a document that is about to be deleted. - // If the ForceSet below causes a garbage collection, the document - // might get deleted and the global handle for the document - // wrapper cleared. Using the cleared global handle will lead to - // crashes. In this case we clear the cache and let the DOMWindow - // accessor handle access to the document. - if (!m_frame->document()->frame()) { - clearDocumentWrapperCache(); - return; - } - - v8::Handle<v8::Value> documentWrapper = V8DOMWrapper::convertNodeToV8Object(m_frame->document()); - - // If instantiation of the document wrapper fails, clear the cache - // and let the DOMWindow accessor handle access to the document. - if (documentWrapper.IsEmpty()) { - clearDocumentWrapperCache(); - return; - } - m_context->Global()->ForceSet(v8::String::New("document"), documentWrapper, static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete)); -} - -void V8Proxy::clearDocumentWrapperCache() -{ - ASSERT(!m_context.IsEmpty()); - m_context->Global()->ForceDelete(v8::String::New("document")); -} - -void V8Proxy::disposeContextHandles() -{ - if (!m_context.IsEmpty()) { - m_frame->loader()->client()->didDestroyScriptContextForFrame(); - m_context.Dispose(); - m_context.Clear(); - } - - if (!m_wrapperBoilerplates.IsEmpty()) { -#ifndef NDEBUG - V8GCController::unregisterGlobalHandle(this, m_wrapperBoilerplates); -#endif - m_wrapperBoilerplates.Dispose(); - m_wrapperBoilerplates.Clear(); - } -} - void V8Proxy::releaseStorageMutex() { // If we've just left a top level script context and local storage has been @@ -804,18 +636,13 @@ void V8Proxy::resetIsolatedWorlds() void V8Proxy::clearForClose() { resetIsolatedWorlds(); - - if (!m_context.IsEmpty()) { - v8::HandleScope handleScope; - - clearDocumentWrapper(); - disposeContextHandles(); - } + windowShell()->clearForClose(); } void V8Proxy::clearForNavigation() { resetIsolatedWorlds(); +<<<<<<< HEAD if (!m_context.IsEmpty()) { v8::HandleScope handle; @@ -1181,6 +1008,9 @@ void V8Proxy::initContextIfNeeded() #ifdef ANDROID_INSTRUMENT android::TimeCounter::record(android::TimeCounter::JavaScriptInitTimeCounter, __FUNCTION__); #endif +======= + windowShell()->clearForNavigation(); +>>>>>>> webkit.org at r54127 } void V8Proxy::setDOMException(int exceptionCode) @@ -1246,8 +1076,8 @@ v8::Local<v8::Context> V8Proxy::context(Frame* frame) if (context.IsEmpty()) return v8::Local<v8::Context>(); - if (V8IsolatedWorld* world = V8IsolatedWorld::getEntered()) { - context = v8::Local<v8::Context>::New(world->context()); + if (V8IsolatedContext* isolatedContext = V8IsolatedContext::getEntered()) { + context = v8::Local<v8::Context>::New(isolatedContext->context()); if (frame != V8Proxy::retrieveFrame(context)) return v8::Local<v8::Context>(); } @@ -1257,8 +1087,8 @@ v8::Local<v8::Context> V8Proxy::context(Frame* frame) v8::Local<v8::Context> V8Proxy::context() { - if (V8IsolatedWorld* world = V8IsolatedWorld::getEntered()) { - RefPtr<SharedPersistent<v8::Context> > context = world->sharedContext(); + if (V8IsolatedContext* isolatedContext = V8IsolatedContext::getEntered()) { + RefPtr<SharedPersistent<v8::Context> > context = isolatedContext->sharedContext(); if (m_frame != V8Proxy::retrieveFrame(context->get())) return v8::Local<v8::Context>(); return v8::Local<v8::Context>::New(context->get()); @@ -1268,8 +1098,8 @@ v8::Local<v8::Context> V8Proxy::context() v8::Local<v8::Context> V8Proxy::mainWorldContext() { - initContextIfNeeded(); - return v8::Local<v8::Context>::New(m_context); + windowShell()->initContextIfNeeded(); + return v8::Local<v8::Context>::New(windowShell()->context()); } v8::Local<v8::Context> V8Proxy::mainWorldContext(Frame* frame) @@ -1427,17 +1257,18 @@ void V8Proxy::registerExtension(v8::Extension* extension, int extensionGroup) bool V8Proxy::setContextDebugId(int debugId) { ASSERT(debugId > 0); - if (m_context.IsEmpty()) - return false; v8::HandleScope scope; - if (!m_context->GetData()->IsUndefined()) + v8::Handle<v8::Context> context = windowShell()->context(); + if (context.IsEmpty()) + return false; + if (!context->GetData()->IsUndefined()) return false; - v8::Context::Scope contextScope(m_context); + v8::Context::Scope contextScope(context); char buffer[32]; snprintf(buffer, sizeof(buffer), "page,%d", debugId); - m_context->SetData(v8::String::New(buffer)); + context->SetData(v8::String::New(buffer)); return true; } @@ -1454,26 +1285,6 @@ int V8Proxy::contextDebugId(v8::Handle<v8::Context> context) return atoi(comma + 1); } -v8::Handle<v8::Value> V8Proxy::getHiddenObjectPrototype(v8::Handle<v8::Context> context) -{ - return context->Global()->GetHiddenValue(V8HiddenPropertyName::objectPrototype()); -} - -void V8Proxy::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; - - v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(context->Global()->Get(objectString)); - v8::Handle<v8::Value> objectPrototype = object->Get(prototypeString); - - context->Global()->SetHiddenValue(hiddenObjectPrototypeString, objectPrototype); -} - v8::Local<v8::Context> toV8Context(ScriptExecutionContext* context, const WorldContextHandle& worldContext) { if (context->isDocument()) { diff --git a/WebCore/bindings/v8/V8Proxy.h b/WebCore/bindings/v8/V8Proxy.h index 900ee18..6f6470e 100644 --- a/WebCore/bindings/v8/V8Proxy.h +++ b/WebCore/bindings/v8/V8Proxy.h @@ -35,6 +35,7 @@ #include "SecurityOrigin.h" // for WebCore::SecurityOrigin #include "SharedPersistent.h" #include "V8AbstractEventListener.h" +#include "V8DOMWindowShell.h" #include "V8DOMWrapper.h" #include "V8GCController.h" #include "V8Index.h" @@ -58,7 +59,7 @@ namespace WebCore { class ScriptExecutionContext; class String; class V8EventListener; - class V8IsolatedWorld; + class V8IsolatedContext; class WorldContextHandle; // FIXME: use standard logging facilities in WebCore. @@ -139,28 +140,21 @@ namespace WebCore { GeneralError }; + // When to report errors. + enum DelayReporting { + ReportLater, + ReportNow + }; + explicit V8Proxy(Frame*); ~V8Proxy(); Frame* frame() { return m_frame; } - // Clear page-specific data, but keep the global object identify. void clearForNavigation(); - - // Clear page-specific data before shutting down the proxy object. void clearForClose(); - // Update document object of the frame. - void updateDocument(); - - // Update the security origin of a document - // (e.g., after setting docoument.domain). - void updateSecurityOrigin(); - - // Destroy the global object. - void destroyGlobal(); - // FIXME: Need comment. User Gesture related. bool inlineCode() const { return m_inlineCode; } void setInlineCode(bool value) { m_inlineCode = value; } @@ -168,9 +162,6 @@ namespace WebCore { bool timerCallback() const { return m_timerCallback; } void setTimerCallback(bool value) { m_timerCallback = value; } - // Has the context for this proxy been initialized? - bool isContextInitialized(); - // Disconnects the proxy from its owner frame, // and clears all timeouts on the DOM window. void disconnectFrame(); @@ -216,11 +207,6 @@ namespace WebCore { // constructors. void evaluateInIsolatedWorld(int worldId, const Vector<ScriptSourceCode>& sources, int extensionGroup); - // Evaluate JavaScript in a new context. The script gets its own global scope - // and its own prototypes for intrinsic JavaScript objects (String, Array, - // and so-on). It shares the wrappers for all DOM nodes and DOM constructors. - void evaluateInNewContext(const Vector<ScriptSourceCode>&, int extensionGroup); - // Evaluate a script file in the current execution environment. // The caller must hold an execution context. // If cannot evalute the script, it returns an error. @@ -239,16 +225,6 @@ namespace WebCore { // 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[]); - // 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) - { - int classIndex = V8ClassIndex::ToInt(type); - v8::Local<v8::Object> clone(m_wrapperBoilerplates->CloneElementAt(classIndex)); - return clone.IsEmpty() ? createWrapperFromCacheSlowCase(type) : clone; - } - // Returns the window object associated with a context. static DOMWindow* retrieveWindow(v8::Handle<v8::Context>); // Returns V8Proxy object of the currently executing context. @@ -305,13 +281,6 @@ namespace WebCore { // is disabled and it returns true. static bool handleOutOfMemory(); - // Check if the active execution context can access the target frame. - static bool canAccessFrame(Frame*, bool reportError); - - // Check if it is safe to access the given node from the - // current security context. - static bool checkNodeSecurity(Node*); - static v8::Handle<v8::Value> checkNewLegal(const v8::Arguments&); static v8::Handle<v8::Script> compileScript(v8::Handle<v8::String> code, const String& fileName, int baseLine); @@ -350,13 +319,12 @@ namespace WebCore { v8::Local<v8::Context> context(); v8::Local<v8::Context> mainWorldContext(); + // FIXME: This should eventually take DOMWrapperWorld argument! + V8DOMWindowShell* windowShell() const { return m_windowShell.get(); } + bool setContextDebugId(int id); static int contextDebugId(v8::Handle<v8::Context>); - static v8::Handle<v8::Value> getHiddenObjectPrototype(v8::Handle<v8::Context>); - // WARNING: Call |installHiddenObjectPrototype| only on fresh contexts! - static void installHiddenObjectPrototype(v8::Handle<v8::Context>); - // Registers a v8 extension to be available on webpages. The two forms // offer various restrictions on what types of contexts the extension is // loaded into. If a scheme is provided, only pages whose URL has the given @@ -367,27 +335,15 @@ namespace WebCore { static void registerExtension(v8::Extension*, const String& schemeRestriction); static void registerExtension(v8::Extension*, int extensionGroup); - // FIXME: Separate these concerns from V8Proxy? - v8::Persistent<v8::Context> createNewContext(v8::Handle<v8::Object> global, int extensionGroup); - static bool installDOMWindow(v8::Handle<v8::Context> context, DOMWindow* window); - - void initContextIfNeeded(); - void updateDocumentWrapper(v8::Handle<v8::Value> wrapper); - - private: - void setSecurityToken(); - void clearDocumentWrapper(); + static void registerExtensionWithV8(v8::Extension*); + static bool registeredExtensionWithV8(v8::Extension*); - // The JavaScript wrapper for the document object is cached on the global - // object for fast access. UpdateDocumentWrapperCache sets the wrapper - // for the current document on the global object. ClearDocumentWrapperCache - // deletes the document wrapper from the global object. - void updateDocumentWrapperCache(); - void clearDocumentWrapperCache(); + static const V8Extensions& extensions() { return m_extensions; } - // Dispose global handles of m_contexts and friends. - void disposeContextHandles(); + // Report an unsafe attempt to access the given frame on the console. + static void reportUnsafeAccessTo(Frame* target, DelayReporting delay); + private: // If m_recursionCount is 0, let LocalStorage know so we can release // the storage mutex. void releaseStorageMutex(); @@ -397,8 +353,6 @@ namespace WebCore { // Returns false when we're out of memory in V8. bool setInjectedScriptContextDebugId(v8::Handle<v8::Context> targetContext); - static bool canAccessPrivate(DOMWindow*); - static const char* rangeExceptionName(int exceptionCode); static const char* eventExceptionName(int exceptionCode); static const char* xmlHttpRequestExceptionName(int exceptionCode); @@ -422,24 +376,11 @@ namespace WebCore { return v8::Local<v8::Context>::New(m_utilityContext); } - v8::Local<v8::Object> createWrapperFromCacheSlowCase(V8ClassIndex::V8WrapperType); - - static void registerExtensionWithV8(v8::Extension*); - static bool registeredExtensionWithV8(v8::Extension*); - Frame* m_frame; - v8::Persistent<v8::Context> m_context; - - // 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; - - v8::Persistent<v8::Object> m_global; - v8::Persistent<v8::Value> m_document; - + // 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; @@ -468,7 +409,10 @@ namespace WebCore { // Note: although the pointer is raw, the instance is kept alive by a strong // reference to the v8 context it contains, which is not made weak until we // call world->destroy(). - typedef HashMap<int, V8IsolatedWorld*> IsolatedWorldMap; + // + // FIXME: We want to eventually be holding window shells instead of the + // IsolatedContext directly. + typedef HashMap<int, V8IsolatedContext*> IsolatedWorldMap; IsolatedWorldMap m_isolatedWorlds; }; diff --git a/WebCore/bindings/v8/V8SVGPODTypeWrapper.h b/WebCore/bindings/v8/V8SVGPODTypeWrapper.h index b6e47af..d4cdcf8 100644 --- a/WebCore/bindings/v8/V8SVGPODTypeWrapper.h +++ b/WebCore/bindings/v8/V8SVGPODTypeWrapper.h @@ -51,6 +51,11 @@ public: virtual ~V8SVGPODTypeWrapper() { } virtual operator PODType() = 0; virtual void commitChange(PODType, SVGElement*) = 0; + + static V8SVGPODTypeWrapper<PODType>* toNative(v8::Handle<v8::Object> object) + { + return reinterpret_cast<V8SVGPODTypeWrapper<PODType>*>(object->GetPointerFromInternalField(v8DOMWrapperObjectIndex)); + } }; template<typename PODType> @@ -59,7 +64,7 @@ public: typedef SVGPODListItem<PODType> PODListItemPtrType; typedef PODType (SVGPODListItem<PODType>::*GetterMethod)() const; - typedef void (SVGPODListItem<PODType>::*SetterMethod)(PODType); + typedef void (SVGPODListItem<PODType>::*SetterMethod)(const PODType&); static PassRefPtr<V8SVGPODTypeWrapperCreatorForList> create(PassRefPtr<PODListItemPtrType> creator, const QualifiedName& attributeName) { @@ -197,7 +202,7 @@ template<typename PODType, typename PODTypeCreator> class V8SVGDynamicPODTypeWrapper : public V8SVGPODTypeWrapper<PODType> { public: typedef PODType (PODTypeCreator::*GetterMethod)() const; - typedef void (PODTypeCreator::*SetterMethod)(PODType); + typedef void (PODTypeCreator::*SetterMethod)(const PODType&); typedef void (*CacheRemovalCallback)(V8SVGPODTypeWrapper<PODType>*); static PassRefPtr<V8SVGDynamicPODTypeWrapper> create(PassRefPtr<PODTypeCreator> creator, GetterMethod getter, SetterMethod setter, CacheRemovalCallback cacheRemovalCallback) @@ -247,7 +252,7 @@ private: template<typename PODType, typename PODTypeCreator> struct PODTypeWrapperCacheInfo { typedef PODType (PODTypeCreator::*GetterMethod)() const; - typedef void (PODTypeCreator::*SetterMethod)(PODType); + typedef void (PODTypeCreator::*SetterMethod)(const PODType&); // Empty value PODTypeWrapperCacheInfo() @@ -338,7 +343,7 @@ template<typename PODType, typename PODTypeCreator> class V8SVGDynamicPODTypeWrapperCache { public: typedef PODType (PODTypeCreator::*GetterMethod)() const; - typedef void (PODTypeCreator::*SetterMethod)(PODType); + typedef void (PODTypeCreator::*SetterMethod)(const PODType&); typedef PODTypeWrapperCacheInfo<PODType, PODTypeCreator> CacheInfo; typedef PODTypeWrapperCacheInfoHash<PODType, PODTypeCreator> CacheInfoHash; @@ -397,14 +402,12 @@ public: template <class P> P V8SVGPODTypeUtil::toSVGPODType(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Value> object, bool& ok) { - void *wrapper = V8DOMWrapper::convertToSVGPODTypeImpl(type, object); - if (wrapper == NULL) { + if (!V8DOMWrapper::isWrapperOfType(object, type)) { ok = false; return P(); - } else { - ok = true; - return *static_cast<V8SVGPODTypeWrapper<P>*>(wrapper); } + ok = true; + return *V8SVGPODTypeWrapper<P>::toNative(v8::Handle<v8::Object>::Cast(object)); } } // namespace WebCore diff --git a/WebCore/bindings/v8/V8Utilities.cpp b/WebCore/bindings/v8/V8Utilities.cpp index c547cc7..fb1ecaa 100644 --- a/WebCore/bindings/v8/V8Utilities.cpp +++ b/WebCore/bindings/v8/V8Utilities.cpp @@ -134,13 +134,15 @@ ScriptExecutionContext* getScriptExecutionContext(ScriptState* scriptState) return proxy->workerContext()->scriptExecutionContext(); #endif - if (scriptState) - return scriptState->frame()->document()->scriptExecutionContext(); - else { - Frame* frame = V8Proxy::retrieveFrameForCurrentContext(); - if (frame) - return frame->document()->scriptExecutionContext(); - } + Frame* frame; + if (scriptState) { + v8::HandleScope handleScope; + frame = V8Proxy::retrieveFrame(scriptState->context()); + } else + frame = V8Proxy::retrieveFrameForCurrentContext(); + + if (frame) + return frame->document()->scriptExecutionContext(); return 0; } @@ -170,7 +172,7 @@ void reportException(ScriptState* scriptState, v8::TryCatch& exceptionCatcher) ScriptExecutionContext* context = getScriptExecutionContext(scriptState); // During the frame teardown, there may not be a valid context. if (context && !context->isDocument()) - context->reportException(errorMessage, lineNumber, sourceURL); + context->reportException(errorMessage, lineNumber, sourceURL); exceptionCatcher.Reset(); } diff --git a/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp b/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp index 412fde0..ac677a2 100644 --- a/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp +++ b/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp @@ -38,6 +38,7 @@ #include "DOMCoreException.h" #include "DedicatedWorkerContext.h" #include "Event.h" +#include "EventSource.h" #include "Notification.h" #include "NotificationCenter.h" #include "EventException.h" @@ -49,6 +50,7 @@ #include "V8DOMMap.h" #include "V8Index.h" #include "V8Proxy.h" +#include "V8WorkerContext.h" #include "V8WorkerContextEventListener.h" #if ENABLE(WEB_SOCKETS) #include "WebSocket.h" @@ -109,7 +111,7 @@ WorkerContextExecutionProxy* WorkerContextExecutionProxy::retrieve() // Return 0 if the current executing context is not the worker context. if (global.IsEmpty()) return 0; - WorkerContext* workerContext = V8DOMWrapper::convertToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, global); + WorkerContext* workerContext = V8WorkerContext::toNative(global); return workerContext->script()->proxy(); } @@ -319,6 +321,18 @@ v8::Handle<v8::Value> WorkerContextExecutionProxy::convertEventTargetToV8Object( if (mp) return convertToV8Object(V8ClassIndex::MESSAGEPORT, mp); +#if ENABLE(WEB_SOCKETS) + WebSocket* webSocket = target->toWebSocket(); + if (webSocket) + return convertToV8Object(V8ClassIndex::WEBSOCKET, webSocket); +#endif + +#if ENABLE(EVENTSOURCE) + EventSource* eventSource = target->toEventSource(); + if (eventSource) + return convertToV8Object(V8ClassIndex::EVENTSOURCE, eventSource); +#endif + ASSERT_NOT_REACHED(); return v8::Handle<v8::Value>(); } diff --git a/WebCore/bindings/v8/WorldContextHandle.cpp b/WebCore/bindings/v8/WorldContextHandle.cpp index eb83586..7ba76d3 100644 --- a/WebCore/bindings/v8/WorldContextHandle.cpp +++ b/WebCore/bindings/v8/WorldContextHandle.cpp @@ -31,7 +31,7 @@ #include "config.h" #include "WorldContextHandle.h" -#include "V8IsolatedWorld.h" +#include "V8IsolatedContext.h" namespace WebCore { @@ -41,8 +41,8 @@ WorldContextHandle::WorldContextHandle(WorldToUse worldToUse) if (worldToUse == UseMainWorld) return; - if (V8IsolatedWorld* world = V8IsolatedWorld::getEntered()) - m_context = world->sharedContext(); + if (V8IsolatedContext* context = V8IsolatedContext::getEntered()) + m_context = context->sharedContext(); } v8::Local<v8::Context> WorldContextHandle::adjustedContext(V8Proxy* proxy) const diff --git a/WebCore/bindings/v8/custom/V8AbstractWorkerCustom.cpp b/WebCore/bindings/v8/custom/V8AbstractWorkerCustom.cpp index 0240895..6b8f195 100644 --- a/WebCore/bindings/v8/custom/V8AbstractWorkerCustom.cpp +++ b/WebCore/bindings/v8/custom/V8AbstractWorkerCustom.cpp @@ -31,9 +31,9 @@ #include "config.h" #if ENABLE(WORKERS) +#include "V8AbstractWorker.h" #include "AbstractWorker.h" - #include "ExceptionCode.h" #include "ScriptExecutionContext.h" #include "V8Binding.h" @@ -44,10 +44,10 @@ namespace WebCore { -CALLBACK_FUNC_DECL(AbstractWorkerAddEventListener) +v8::Handle<v8::Value> V8AbstractWorker::addEventListenerCallback(const v8::Arguments& args) { INC_STATS(L"DOM.AbstractWorker.addEventListener()"); - AbstractWorker* worker = V8DOMWrapper::convertToNativeObject<AbstractWorker>(V8ClassIndex::ABSTRACTWORKER, args.Holder()); + AbstractWorker* worker = V8AbstractWorker::toNative(args.Holder()); RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(worker, args[1], false, ListenerFindOrCreate); if (listener) { @@ -55,15 +55,15 @@ CALLBACK_FUNC_DECL(AbstractWorkerAddEventListener) bool useCapture = args[2]->BooleanValue(); worker->addEventListener(type, listener, useCapture); - createHiddenDependency(args.Holder(), args[1], V8Custom::kAbstractWorkerRequestCacheIndex); + createHiddenDependency(args.Holder(), args[1], cacheIndex); } return v8::Undefined(); } -CALLBACK_FUNC_DECL(AbstractWorkerRemoveEventListener) +v8::Handle<v8::Value> V8AbstractWorker::removeEventListenerCallback(const v8::Arguments& args) { INC_STATS(L"DOM.AbstractWorker.removeEventListener()"); - AbstractWorker* worker = V8DOMWrapper::convertToNativeObject<AbstractWorker>(V8ClassIndex::ABSTRACTWORKER, args.Holder()); + AbstractWorker* worker = V8AbstractWorker::toNative(args.Holder()); RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(worker, args[1], false, ListenerFindOnly); if (listener) { @@ -71,7 +71,7 @@ CALLBACK_FUNC_DECL(AbstractWorkerRemoveEventListener) bool useCapture = args[2]->BooleanValue(); worker->removeEventListener(type, listener.get(), useCapture); - removeHiddenDependency(args.Holder(), args[1], V8Custom::kAbstractWorkerRequestCacheIndex); + removeHiddenDependency(args.Holder(), args[1], cacheIndex); } return v8::Undefined(); diff --git a/WebCore/bindings/v8/custom/V8AttrCustom.cpp b/WebCore/bindings/v8/custom/V8AttrCustom.cpp index 81f1586..7bec619 100644 --- a/WebCore/bindings/v8/custom/V8AttrCustom.cpp +++ b/WebCore/bindings/v8/custom/V8AttrCustom.cpp @@ -29,24 +29,25 @@ */ #include "config.h" -#include "Attr.h" +#include "V8Attr.h" +#include "Attr.h" #include "Element.h" #include "ExceptionCode.h" - #include "V8Binding.h" +#include "V8BindingState.h" #include "V8CustomBinding.h" #include "V8Proxy.h" namespace WebCore { -ACCESSOR_SETTER(AttrValue) +void V8Attr::valueAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { - Attr* imp = V8DOMWrapper::convertDOMWrapperToNode<Attr>(info.Holder()); + Attr* imp = V8Attr::toNative(info.Holder()); String attrValue = toWebCoreStringWithNullCheck(value); Element* ownerElement = imp->ownerElement(); - if (ownerElement && !allowSettingSrcToJavascriptURL(ownerElement, imp->name(), attrValue)) + if (ownerElement && !V8BindingSecurity::allowSettingSrcToJavascriptURL(V8BindingState::Only(), ownerElement, imp->name(), attrValue)) return; ExceptionCode ec = 0; diff --git a/WebCore/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp b/WebCore/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp index 6bd0035..25d141a 100644 --- a/WebCore/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp +++ b/WebCore/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp @@ -29,9 +29,10 @@ */ #include "config.h" -#include "CSSStyleDeclaration.h" +#include "V8CSSStyleDeclaration.h" #include "CSSParser.h" +#include "CSSStyleDeclaration.h" #include "CSSValue.h" #include "CSSPrimitiveValue.h" #include "EventTarget.h" @@ -152,7 +153,7 @@ static CSSPropertyInfo* cssPropertyInfo(v8::Handle<v8::String>v8PropertyName) return propInfo; } -NAMED_PROPERTY_GETTER(CSSStyleDeclaration) +v8::Handle<v8::Value> V8CSSStyleDeclaration::namedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.CSSStyleDeclaration.NamedPropertyGetter"); // First look for API defined attributes on the style declaration object. @@ -160,8 +161,7 @@ NAMED_PROPERTY_GETTER(CSSStyleDeclaration) return notHandledByInterceptor(); // Search the style declaration. - CSSStyleDeclaration* imp = - V8DOMWrapper::convertToNativeObject<CSSStyleDeclaration>(V8ClassIndex::CSSSTYLEDECLARATION, info.Holder()); + CSSStyleDeclaration* imp = V8CSSStyleDeclaration::toNative(info.Holder()); CSSPropertyInfo* propInfo = cssPropertyInfo(name); // Do not handle non-property names. @@ -191,12 +191,10 @@ NAMED_PROPERTY_GETTER(CSSStyleDeclaration) return v8String(result); } -NAMED_PROPERTY_SETTER(CSSStyleDeclaration) +v8::Handle<v8::Value> V8CSSStyleDeclaration::namedPropertySetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { INC_STATS("DOM.CSSStyleDeclaration.NamedPropertySetter"); - CSSStyleDeclaration* imp = - V8DOMWrapper::convertToNativeObject<CSSStyleDeclaration>( - V8ClassIndex::CSSSTYLEDECLARATION, info.Holder()); + CSSStyleDeclaration* imp = V8CSSStyleDeclaration::toNative(info.Holder()); CSSPropertyInfo* propInfo = cssPropertyInfo(name); if (!propInfo) return notHandledByInterceptor(); diff --git a/WebCore/bindings/v8/custom/V8CanvasRenderingContext2DCustom.cpp b/WebCore/bindings/v8/custom/V8CanvasRenderingContext2DCustom.cpp index 676610c..b45ef35 100644 --- a/WebCore/bindings/v8/custom/V8CanvasRenderingContext2DCustom.cpp +++ b/WebCore/bindings/v8/custom/V8CanvasRenderingContext2DCustom.cpp @@ -29,9 +29,10 @@ */ #include "config.h" -#include "CanvasRenderingContext2D.h" +#include "V8CanvasRenderingContext2D.h" #include "CanvasGradient.h" +#include "CanvasRenderingContext2D.h" #include "CanvasPattern.h" #include "CanvasStyle.h" #include "ExceptionCode.h" @@ -44,6 +45,7 @@ #include "V8HTMLCanvasElement.h" #include "V8HTMLImageElement.h" #include "V8HTMLVideoElement.h" +#include "V8ImageData.h" #include "V8Proxy.h" namespace WebCore { @@ -65,44 +67,44 @@ static PassRefPtr<CanvasStyle> toCanvasStyle(v8::Handle<v8::Value> value) return CanvasStyle::create(toWebCoreString(value)); if (V8CanvasGradient::HasInstance(value)) - return CanvasStyle::create(V8DOMWrapper::convertDOMWrapperToNative<CanvasGradient>(v8::Handle<v8::Object>::Cast(value))); + return CanvasStyle::create(V8CanvasGradient::toNative(v8::Handle<v8::Object>::Cast(value))); if (V8CanvasPattern::HasInstance(value)) - return CanvasStyle::create(V8DOMWrapper::convertDOMWrapperToNative<CanvasPattern>(v8::Handle<v8::Object>::Cast(value))); + return CanvasStyle::create(V8CanvasPattern::toNative(v8::Handle<v8::Object>::Cast(value))); return 0; } -ACCESSOR_GETTER(CanvasRenderingContext2DStrokeStyle) +v8::Handle<v8::Value> V8CanvasRenderingContext2D::strokeStyleAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { - CanvasRenderingContext2D* impl = V8DOMWrapper::convertDOMWrapperToNative<CanvasRenderingContext2D>(info.Holder()); + CanvasRenderingContext2D* impl = V8CanvasRenderingContext2D::toNative(info.Holder()); return toV8(impl->strokeStyle()); } -ACCESSOR_SETTER(CanvasRenderingContext2DStrokeStyle) +void V8CanvasRenderingContext2D::strokeStyleAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { - CanvasRenderingContext2D* impl = V8DOMWrapper::convertDOMWrapperToNative<CanvasRenderingContext2D>(info.Holder()); + CanvasRenderingContext2D* impl = V8CanvasRenderingContext2D::toNative(info.Holder()); impl->setStrokeStyle(toCanvasStyle(value)); } -ACCESSOR_GETTER(CanvasRenderingContext2DFillStyle) +v8::Handle<v8::Value> V8CanvasRenderingContext2D::fillStyleAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { - CanvasRenderingContext2D* impl = V8DOMWrapper::convertDOMWrapperToNative<CanvasRenderingContext2D>(info.Holder()); + CanvasRenderingContext2D* impl = V8CanvasRenderingContext2D::toNative(info.Holder()); return toV8(impl->fillStyle()); } -ACCESSOR_SETTER(CanvasRenderingContext2DFillStyle) +void V8CanvasRenderingContext2D::fillStyleAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { - CanvasRenderingContext2D* impl = V8DOMWrapper::convertDOMWrapperToNative<CanvasRenderingContext2D>(info.Holder()); + CanvasRenderingContext2D* impl = V8CanvasRenderingContext2D::toNative(info.Holder()); impl->setFillStyle(toCanvasStyle(value)); } // TODO: SetStrokeColor and SetFillColor are similar except function names, // consolidate them into one. -CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetStrokeColor) +v8::Handle<v8::Value> V8CanvasRenderingContext2D::setStrokeColorCallback(const v8::Arguments& args) { INC_STATS("DOM.CanvasRenderingContext2D.setStrokeColor()"); - CanvasRenderingContext2D* context = V8DOMWrapper::convertToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); + CanvasRenderingContext2D* context = V8CanvasRenderingContext2D::toNative(args.Holder()); switch (args.Length()) { case 1: if (args[0]->IsString()) @@ -129,10 +131,10 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetStrokeColor) return v8::Undefined(); } -CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetFillColor) +v8::Handle<v8::Value> V8CanvasRenderingContext2D::setFillColorCallback(const v8::Arguments& args) { INC_STATS("DOM.CanvasRenderingContext2D.setFillColor()"); - CanvasRenderingContext2D* context = V8DOMWrapper::convertToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); + CanvasRenderingContext2D* context = V8CanvasRenderingContext2D::toNative(args.Holder()); switch (args.Length()) { case 1: if (args[0]->IsString()) @@ -159,10 +161,10 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetFillColor) return v8::Undefined(); } -CALLBACK_FUNC_DECL(CanvasRenderingContext2DStrokeRect) +v8::Handle<v8::Value> V8CanvasRenderingContext2D::strokeRectCallback(const v8::Arguments& args) { INC_STATS("DOM.CanvasRenderingContext2D.strokeRect()"); - CanvasRenderingContext2D* context = V8DOMWrapper::convertToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); + 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) @@ -174,10 +176,10 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DStrokeRect) return v8::Undefined(); } -CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetShadow) +v8::Handle<v8::Value> V8CanvasRenderingContext2D::setShadowCallback(const v8::Arguments& args) { INC_STATS("DOM.CanvasRenderingContext2D.setShadow()"); - CanvasRenderingContext2D* context = V8DOMWrapper::convertToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); + CanvasRenderingContext2D* context = V8CanvasRenderingContext2D::toNative(args.Holder()); switch (args.Length()) { case 3: @@ -209,29 +211,29 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetShadow) return v8::Undefined(); } -CALLBACK_FUNC_DECL(CanvasRenderingContext2DDrawImage) +v8::Handle<v8::Value> V8CanvasRenderingContext2D::drawImageCallback(const v8::Arguments& args) { INC_STATS("DOM.CanvasRenderingContext2D.drawImage()"); - CanvasRenderingContext2D* context = V8DOMWrapper::convertToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); + CanvasRenderingContext2D* context = V8CanvasRenderingContext2D::toNative(args.Holder()); v8::Handle<v8::Value> arg = args[0]; if (V8HTMLImageElement::HasInstance(arg)) { ExceptionCode ec = 0; - HTMLImageElement* image_element = V8DOMWrapper::convertDOMWrapperToNode<HTMLImageElement>(v8::Handle<v8::Object>::Cast(arg)); + HTMLImageElement* imageElement = V8HTMLImageElement::toNative(v8::Handle<v8::Object>::Cast(arg)); switch (args.Length()) { case 3: - context->drawImage(image_element, toFloat(args[1]), toFloat(args[2])); + context->drawImage(imageElement, toFloat(args[1]), toFloat(args[2])); break; case 5: - context->drawImage(image_element, toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4]), ec); + 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(image_element, + 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); @@ -249,20 +251,20 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DDrawImage) // HTMLCanvasElement if (V8HTMLCanvasElement::HasInstance(arg)) { ExceptionCode ec = 0; - HTMLCanvasElement* canvas_element = V8DOMWrapper::convertDOMWrapperToNode<HTMLCanvasElement>(v8::Handle<v8::Object>::Cast(arg)); + HTMLCanvasElement* canvasElement = V8HTMLCanvasElement::toNative(v8::Handle<v8::Object>::Cast(arg)); switch (args.Length()) { case 3: - context->drawImage(canvas_element, toFloat(args[1]), toFloat(args[2])); + context->drawImage(canvasElement, toFloat(args[1]), toFloat(args[2])); break; case 5: - context->drawImage(canvas_element, toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4]), ec); + 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(canvas_element, + 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); @@ -281,20 +283,20 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DDrawImage) // HTMLVideoElement if (V8HTMLVideoElement::HasInstance(arg)) { ExceptionCode ec = 0; - HTMLVideoElement* video_element = V8DOMWrapper::convertDOMWrapperToNode<HTMLVideoElement>(v8::Handle<v8::Object>::Cast(arg)); + HTMLVideoElement* videoElement = V8HTMLVideoElement::toNative(v8::Handle<v8::Object>::Cast(arg)); switch (args.Length()) { case 3: - context->drawImage(video_element, toFloat(args[1]), toFloat(args[2])); + context->drawImage(videoElement, toFloat(args[1]), toFloat(args[2])); break; case 5: - context->drawImage(video_element, toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4]), ec); + 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(video_element, + 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); @@ -314,33 +316,34 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DDrawImage) return notHandledByInterceptor(); } -CALLBACK_FUNC_DECL(CanvasRenderingContext2DDrawImageFromRect) + +v8::Handle<v8::Value> V8CanvasRenderingContext2D::drawImageFromRectCallback(const v8::Arguments& args) { INC_STATS("DOM.CanvasRenderingContext2D.drawImageFromRect()"); - CanvasRenderingContext2D* context = V8DOMWrapper::convertToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); + CanvasRenderingContext2D* context = V8CanvasRenderingContext2D::toNative(args.Holder()); v8::Handle<v8::Value> arg = args[0]; if (V8HTMLImageElement::HasInstance(arg)) { - HTMLImageElement* image_element = V8DOMWrapper::convertDOMWrapperToNode<HTMLImageElement>(v8::Handle<v8::Object>::Cast(arg)); - context->drawImageFromRect(image_element, 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])); + 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(); } -CALLBACK_FUNC_DECL(CanvasRenderingContext2DCreatePattern) +v8::Handle<v8::Value> V8CanvasRenderingContext2D::createPatternCallback(const v8::Arguments& args) { INC_STATS("DOM.CanvasRenderingContext2D.createPattern()"); - CanvasRenderingContext2D* context = V8DOMWrapper::convertToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); + CanvasRenderingContext2D* context = V8CanvasRenderingContext2D::toNative(args.Holder()); v8::Handle<v8::Value> arg = args[0]; if (V8HTMLImageElement::HasInstance(arg)) { - HTMLImageElement* image_element = V8DOMWrapper::convertDOMWrapperToNode<HTMLImageElement>(v8::Handle<v8::Object>::Cast(arg)); + HTMLImageElement* imageElement = V8HTMLImageElement::toNative(v8::Handle<v8::Object>::Cast(arg)); ExceptionCode ec = 0; - RefPtr<CanvasPattern> pattern = context->createPattern(image_element, toWebCoreStringWithNullCheck(args[1]), ec); + RefPtr<CanvasPattern> pattern = context->createPattern(imageElement, toWebCoreStringWithNullCheck(args[1]), ec); if (ec != 0) { V8Proxy::setDOMException(ec); return notHandledByInterceptor(); @@ -349,9 +352,9 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DCreatePattern) } if (V8HTMLCanvasElement::HasInstance(arg)) { - HTMLCanvasElement* canvas_element = V8DOMWrapper::convertDOMWrapperToNode<HTMLCanvasElement>(v8::Handle<v8::Object>::Cast(arg)); + HTMLCanvasElement* canvasElement = V8HTMLCanvasElement::toNative(v8::Handle<v8::Object>::Cast(arg)); ExceptionCode ec = 0; - RefPtr<CanvasPattern> pattern = context->createPattern(canvas_element, toWebCoreStringWithNullCheck(args[1]), ec); + RefPtr<CanvasPattern> pattern = context->createPattern(canvasElement, toWebCoreStringWithNullCheck(args[1]), ec); if (ec != 0) { V8Proxy::setDOMException(ec); return notHandledByInterceptor(); @@ -363,11 +366,11 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DCreatePattern) return notHandledByInterceptor(); } -CALLBACK_FUNC_DECL(CanvasRenderingContext2DFillText) +v8::Handle<v8::Value> V8CanvasRenderingContext2D::fillTextCallback(const v8::Arguments& args) { INC_STATS("DOM.CanvasRenderingContext2D.fillText()"); - CanvasRenderingContext2D* context = V8DOMWrapper::convertToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); + CanvasRenderingContext2D* context = V8CanvasRenderingContext2D::toNative(args.Holder()); // Two forms: // * fillText(text, x, y) @@ -390,10 +393,10 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DFillText) return v8::Undefined(); } -CALLBACK_FUNC_DECL(CanvasRenderingContext2DStrokeText) +v8::Handle<v8::Value> V8CanvasRenderingContext2D::strokeTextCallback(const v8::Arguments& args) { INC_STATS("DOM.CanvasRenderingContext2D.strokeText()"); - CanvasRenderingContext2D* context = V8DOMWrapper::convertToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); + CanvasRenderingContext2D* context = V8CanvasRenderingContext2D::toNative(args.Holder()); // Two forms: // * strokeText(text, x, y) @@ -416,7 +419,7 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DStrokeText) return v8::Undefined(); } -CALLBACK_FUNC_DECL(CanvasRenderingContext2DPutImageData) +v8::Handle<v8::Value> V8CanvasRenderingContext2D::putImageDataCallback(const v8::Arguments& args) { INC_STATS("DOM.CanvasRenderingContext2D.putImageData()"); @@ -428,16 +431,16 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DPutImageData) return notHandledByInterceptor(); } - CanvasRenderingContext2D* context = V8DOMWrapper::convertToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); + CanvasRenderingContext2D* context = V8CanvasRenderingContext2D::toNative(args.Holder()); ImageData* imageData = 0; // Need to check that the argument is of the correct type, since - // convertToNativeObject() expects it to be correct. If the argument was incorrect + // 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 = V8DOMWrapper::convertToNativeObject<ImageData>(V8ClassIndex::IMAGEDATA, v8::Handle<v8::Object>::Cast(args[0])); + imageData = V8ImageData::toNative(v8::Handle<v8::Object>::Cast(args[0])); ExceptionCode ec = 0; diff --git a/WebCore/bindings/v8/custom/V8ClipboardCustom.cpp b/WebCore/bindings/v8/custom/V8ClipboardCustom.cpp index 4526304..5f0b4e3 100644 --- a/WebCore/bindings/v8/custom/V8ClipboardCustom.cpp +++ b/WebCore/bindings/v8/custom/V8ClipboardCustom.cpp @@ -29,8 +29,9 @@ */ #include "config.h" -#include "Clipboard.h" +#include "V8Clipboard.h" +#include "Clipboard.h" #include "HTMLImageElement.h" #include "HTMLNames.h" #include "IntPoint.h" @@ -44,10 +45,10 @@ namespace WebCore { -ACCESSOR_GETTER(ClipboardTypes) +v8::Handle<v8::Value> V8Clipboard::typesAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.Clipboard.types()"); - Clipboard* clipboard = V8DOMWrapper::convertToNativeObject<Clipboard>(V8ClassIndex::CLIPBOARD, info.Holder()); + Clipboard* clipboard = V8Clipboard::toNative(info.Holder()); HashSet<String> types = clipboard->types(); if (types.isEmpty()) @@ -62,10 +63,10 @@ ACCESSOR_GETTER(ClipboardTypes) return result; } -CALLBACK_FUNC_DECL(ClipboardClearData) +v8::Handle<v8::Value> V8Clipboard::clearDataCallback(const v8::Arguments& args) { INC_STATS("DOM.Clipboard.clearData()"); - Clipboard* clipboard = V8DOMWrapper::convertToNativeObject<Clipboard>(V8ClassIndex::CLIPBOARD, args.Holder()); + Clipboard* clipboard = V8Clipboard::toNative(args.Holder()); if (!args.Length()) { clipboard->clearAllData(); @@ -80,10 +81,10 @@ CALLBACK_FUNC_DECL(ClipboardClearData) return v8::Undefined(); } -CALLBACK_FUNC_DECL(ClipboardGetData) +v8::Handle<v8::Value> V8Clipboard::getDataCallback(const v8::Arguments& args) { INC_STATS("DOM.Clipboard.getData()"); - Clipboard* clipboard = V8DOMWrapper::convertToNativeObject<Clipboard>(V8ClassIndex::CLIPBOARD, args.Holder()); + Clipboard* clipboard = V8Clipboard::toNative(args.Holder()); if (args.Length() != 1) return throwError("getData: Invalid number of arguments", V8Proxy::SyntaxError); @@ -96,10 +97,10 @@ CALLBACK_FUNC_DECL(ClipboardGetData) return v8::Undefined(); } -CALLBACK_FUNC_DECL(ClipboardSetData) +v8::Handle<v8::Value> V8Clipboard::setDataCallback(const v8::Arguments& args) { INC_STATS("DOM.Clipboard.setData()"); - Clipboard* clipboard = V8DOMWrapper::convertToNativeObject<Clipboard>(V8ClassIndex::CLIPBOARD, args.Holder()); + Clipboard* clipboard = V8Clipboard::toNative(args.Holder()); if (args.Length() != 2) return throwError("setData: Invalid number of arguments", V8Proxy::SyntaxError); @@ -109,10 +110,10 @@ CALLBACK_FUNC_DECL(ClipboardSetData) return v8Boolean(clipboard->setData(type, data)); } -CALLBACK_FUNC_DECL(ClipboardSetDragImage) +v8::Handle<v8::Value> V8Clipboard::setDragImageCallback(const v8::Arguments& args) { INC_STATS("DOM.Clipboard.setDragImage()"); - Clipboard* clipboard = V8DOMWrapper::convertToNativeObject<Clipboard>(V8ClassIndex::CLIPBOARD, args.Holder()); + Clipboard* clipboard = V8Clipboard::toNative(args.Holder()); if (!clipboard->isForDragging()) return v8::Undefined(); @@ -125,7 +126,7 @@ CALLBACK_FUNC_DECL(ClipboardSetDragImage) Node* node = 0; if (V8Node::HasInstance(args[0])) - node = V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])); + node = V8Node::toNative(v8::Handle<v8::Object>::Cast(args[0])); if (!node || !node->isElementNode()) return throwError("setDragImageFromElement: Invalid first argument"); diff --git a/WebCore/bindings/v8/custom/V8ConsoleCustom.cpp b/WebCore/bindings/v8/custom/V8ConsoleCustom.cpp index b44e074..0dbdcd7 100644 --- a/WebCore/bindings/v8/custom/V8ConsoleCustom.cpp +++ b/WebCore/bindings/v8/custom/V8ConsoleCustom.cpp @@ -29,6 +29,7 @@ */ #include "config.h" +#include "V8Console.h" #include "V8Binding.h" #include "V8CustomBinding.h" @@ -37,7 +38,7 @@ namespace WebCore { -CALLBACK_FUNC_DECL(ConsoleProfile) +v8::Handle<v8::Value> V8Console::profileCallback(const v8::Arguments& args) { INC_STATS("console.profile()"); v8::HandleScope scope; @@ -46,7 +47,7 @@ CALLBACK_FUNC_DECL(ConsoleProfile) return v8::Undefined(); } -CALLBACK_FUNC_DECL(ConsoleProfileEnd) +v8::Handle<v8::Value> V8Console::profileEndCallback(const v8::Arguments& args) { INC_STATS("console.profileEnd()"); v8::V8::PauseProfiler(); diff --git a/WebCore/bindings/v8/custom/V8CoordinatesCustom.cpp b/WebCore/bindings/v8/custom/V8CoordinatesCustom.cpp index 1c07f29..a5197f5 100644 --- a/WebCore/bindings/v8/custom/V8CoordinatesCustom.cpp +++ b/WebCore/bindings/v8/custom/V8CoordinatesCustom.cpp @@ -24,49 +24,50 @@ */ #include "config.h" -#include "Coordinates.h" +#include "V8Coordinates.h" +#include "Coordinates.h" #include "V8Binding.h" #include "V8CustomBinding.h" #include "V8Proxy.h" namespace WebCore { -ACCESSOR_GETTER(CoordinatesAltitude) +v8::Handle<v8::Value> V8Coordinates::altitudeAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.Coordinates.altitude._get"); v8::Handle<v8::Object> holder = info.Holder(); - Coordinates* imp = V8DOMWrapper::convertToNativeObject<Coordinates>(V8ClassIndex::COORDINATES, holder); + Coordinates* imp = V8Coordinates::toNative(holder); if (!imp->canProvideAltitude()) return v8::Null(); return v8::Number::New(imp->altitude()); } -ACCESSOR_GETTER(CoordinatesAltitudeAccuracy) +v8::Handle<v8::Value> V8Coordinates::altitudeAccuracyAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.Coordinates.altitudeAccuracy._get"); v8::Handle<v8::Object> holder = info.Holder(); - Coordinates* imp = V8DOMWrapper::convertToNativeObject<Coordinates>(V8ClassIndex::COORDINATES, holder); + Coordinates* imp = V8Coordinates::toNative(holder); if (!imp->canProvideAltitudeAccuracy()) return v8::Null(); return v8::Number::New(imp->altitudeAccuracy()); } -ACCESSOR_GETTER(CoordinatesHeading) +v8::Handle<v8::Value> V8Coordinates::headingAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.Coordinates.heading._get"); v8::Handle<v8::Object> holder = info.Holder(); - Coordinates* imp = V8DOMWrapper::convertToNativeObject<Coordinates>(V8ClassIndex::COORDINATES, holder); + Coordinates* imp = V8Coordinates::toNative(holder); if (!imp->canProvideHeading()) return v8::Null(); return v8::Number::New(imp->heading()); } -ACCESSOR_GETTER(CoordinatesSpeed) +v8::Handle<v8::Value> V8Coordinates::speedAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.Coordinates.speed._get"); v8::Handle<v8::Object> holder = info.Holder(); - Coordinates* imp = V8DOMWrapper::convertToNativeObject<Coordinates>(V8ClassIndex::COORDINATES, holder); + Coordinates* imp = V8Coordinates::toNative(holder); if (!imp->canProvideSpeed()) return v8::Null(); return v8::Number::New(imp->speed()); diff --git a/WebCore/bindings/v8/custom/V8CustomBinding.cpp b/WebCore/bindings/v8/custom/V8CustomBinding.cpp deleted file mode 100644 index 510aded..0000000 --- a/WebCore/bindings/v8/custom/V8CustomBinding.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (C) 2007-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 "V8CustomBinding.h" - -#include "CSSHelper.h" -#include "Element.h" -#include "Document.h" -#include "DOMWindow.h" -#include "History.h" -#include "HTMLNames.h" -#include "HTMLFrameElementBase.h" -#include "Location.h" -#include "V8Proxy.h" - -#if ENABLE(SVG) -#include "SVGPathSeg.h" -#endif - -namespace WebCore { - -bool allowSettingFrameSrcToJavascriptUrl(HTMLFrameElementBase* frame, String value) -{ - if (protocolIs(deprecatedParseURL(value), "javascript")) { - Node* contentDoc = frame->contentDocument(); - if (contentDoc && !V8Proxy::checkNodeSecurity(contentDoc)) - return false; - } - return true; -} - -bool allowSettingSrcToJavascriptURL(Element* element, String name, String value) -{ - if ((element->hasTagName(HTMLNames::iframeTag) || element->hasTagName(HTMLNames::frameTag)) && equalIgnoringCase(name, "src")) - return allowSettingFrameSrcToJavascriptUrl(static_cast<HTMLFrameElementBase*>(element), value); - return true; -} - -// DOMImplementation is a singleton in WebCore. If we use our normal -// mapping from DOM objects to V8 wrappers, the same wrapper will be -// shared for all frames in the same process. This is a major -// security problem. Therefore, we generate a DOMImplementation -// wrapper per document and store it in an internal field of the -// document. Since the DOMImplementation object is a singleton, we do -// not have to do anything to keep the DOMImplementation object alive -// for the lifetime of the wrapper. -ACCESSOR_GETTER(DocumentImplementation) -{ - ASSERT(info.Holder()->InternalFieldCount() >= kDocumentMinimumInternalFieldCount); - - // Check if the internal field already contains a wrapper. - v8::Local<v8::Value> implementation = info.Holder()->GetInternalField(kDocumentImplementationIndex); - if (!implementation->IsUndefined()) - return implementation; - - // Generate a wrapper. - Document* document = V8DOMWrapper::convertDOMWrapperToNative<Document>(info.Holder()); - v8::Handle<v8::Value> wrapper = V8DOMWrapper::convertDOMImplementationToV8Object(document->implementation()); - - // Store the wrapper in the internal field. - info.Holder()->SetInternalField(kDocumentImplementationIndex, wrapper); - - return wrapper; -} - -// --------------- Security Checks ------------------------- -INDEXED_ACCESS_CHECK(History) -{ - ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::HISTORY); - // Only allow same origin access. - History* history = V8DOMWrapper::convertToNativeObject<History>(V8ClassIndex::HISTORY, host); - return V8Proxy::canAccessFrame(history->frame(), false); -} - -NAMED_ACCESS_CHECK(History) -{ - ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::HISTORY); - // Only allow same origin access. - History* history = V8DOMWrapper::convertToNativeObject<History>(V8ClassIndex::HISTORY, host); - return V8Proxy::canAccessFrame(history->frame(), false); -} - -#undef INDEXED_ACCESS_CHECK -#undef NAMED_ACCESS_CHECK -#undef NAMED_PROPERTY_GETTER -#undef NAMED_PROPERTY_SETTER - -Frame* V8Custom::GetTargetFrame(v8::Local<v8::Object> host, v8::Local<v8::Value> data) -{ - Frame* target = 0; - switch (V8ClassIndex::FromInt(data->Int32Value())) { - case V8ClassIndex::DOMWINDOW: { - v8::Handle<v8::Object> window = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, host); - if (window.IsEmpty()) - return target; - - DOMWindow* targetWindow = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, window); - target = targetWindow->frame(); - break; - } - case V8ClassIndex::LOCATION: { - History* history = V8DOMWrapper::convertToNativeObject<History>(V8ClassIndex::HISTORY, host); - target = history->frame(); - break; - } - case V8ClassIndex::HISTORY: { - Location* location = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, host); - target = location->frame(); - break; - } - default: - break; - } - return target; -} - -#if ENABLE(SVG) -V8ClassIndex::V8WrapperType V8Custom::DowncastSVGPathSeg(void* pathSeg) -{ - WebCore::SVGPathSeg* realPathSeg = reinterpret_cast<WebCore::SVGPathSeg*>(pathSeg); - - switch (realPathSeg->pathSegType()) { -#define MAKE_CASE(svgValue, v8Value) case WebCore::SVGPathSeg::svgValue: return V8ClassIndex::v8Value - - MAKE_CASE(PATHSEG_CLOSEPATH, SVGPATHSEGCLOSEPATH); - MAKE_CASE(PATHSEG_MOVETO_ABS, SVGPATHSEGMOVETOABS); - MAKE_CASE(PATHSEG_MOVETO_REL, SVGPATHSEGMOVETOREL); - MAKE_CASE(PATHSEG_LINETO_ABS, SVGPATHSEGLINETOABS); - MAKE_CASE(PATHSEG_LINETO_REL, SVGPATHSEGLINETOREL); - MAKE_CASE(PATHSEG_CURVETO_CUBIC_ABS, SVGPATHSEGCURVETOCUBICABS); - MAKE_CASE(PATHSEG_CURVETO_CUBIC_REL, SVGPATHSEGCURVETOCUBICREL); - MAKE_CASE(PATHSEG_CURVETO_QUADRATIC_ABS, SVGPATHSEGCURVETOQUADRATICABS); - MAKE_CASE(PATHSEG_CURVETO_QUADRATIC_REL, SVGPATHSEGCURVETOQUADRATICREL); - MAKE_CASE(PATHSEG_ARC_ABS, SVGPATHSEGARCABS); - MAKE_CASE(PATHSEG_ARC_REL, SVGPATHSEGARCREL); - MAKE_CASE(PATHSEG_LINETO_HORIZONTAL_ABS, SVGPATHSEGLINETOHORIZONTALABS); - MAKE_CASE(PATHSEG_LINETO_HORIZONTAL_REL, SVGPATHSEGLINETOHORIZONTALREL); - MAKE_CASE(PATHSEG_LINETO_VERTICAL_ABS, SVGPATHSEGLINETOVERTICALABS); - MAKE_CASE(PATHSEG_LINETO_VERTICAL_REL, SVGPATHSEGLINETOVERTICALREL); - MAKE_CASE(PATHSEG_CURVETO_CUBIC_SMOOTH_ABS, SVGPATHSEGCURVETOCUBICSMOOTHABS); - MAKE_CASE(PATHSEG_CURVETO_CUBIC_SMOOTH_REL, SVGPATHSEGCURVETOCUBICSMOOTHREL); - MAKE_CASE(PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS, SVGPATHSEGCURVETOQUADRATICSMOOTHABS); - MAKE_CASE(PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL, SVGPATHSEGCURVETOQUADRATICSMOOTHREL); - -#undef MAKE_CASE - - default: - return V8ClassIndex::INVALID_CLASS_INDEX; - } -} - -#endif // ENABLE(SVG) - -} // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8CustomBinding.h b/WebCore/bindings/v8/custom/V8CustomBinding.h index e7670b7..25f4507 100644 --- a/WebCore/bindings/v8/custom/V8CustomBinding.h +++ b/WebCore/bindings/v8/custom/V8CustomBinding.h @@ -34,308 +34,16 @@ #include "V8Index.h" #include <v8.h> -struct NPObject; - -#define CALLBACK_FUNC_DECL(NAME) v8::Handle<v8::Value> V8Custom::v8##NAME##Callback(const v8::Arguments& args) - -#define ACCESSOR_GETTER(NAME) \ - v8::Handle<v8::Value> V8Custom::v8##NAME##AccessorGetter( \ - v8::Local<v8::String> name, const v8::AccessorInfo& info) - -#define ACCESSOR_SETTER(NAME) \ - void V8Custom::v8##NAME##AccessorSetter(v8::Local<v8::String> name, \ - v8::Local<v8::Value> value, const v8::AccessorInfo& info) - -#define INDEXED_PROPERTY_GETTER(NAME) \ - v8::Handle<v8::Value> V8Custom::v8##NAME##IndexedPropertyGetter( \ - uint32_t index, const v8::AccessorInfo& info) - -#define INDEXED_PROPERTY_SETTER(NAME) \ - v8::Handle<v8::Value> V8Custom::v8##NAME##IndexedPropertySetter( \ - uint32_t index, v8::Local<v8::Value> value, const v8::AccessorInfo& info) - -#define INDEXED_PROPERTY_DELETER(NAME) \ - v8::Handle<v8::Boolean> V8Custom::v8##NAME##IndexedPropertyDeleter( \ - uint32_t index, const v8::AccessorInfo& info) - -#define NAMED_PROPERTY_GETTER(NAME) \ - v8::Handle<v8::Value> V8Custom::v8##NAME##NamedPropertyGetter( \ - v8::Local<v8::String> name, const v8::AccessorInfo& info) - -#define NAMED_PROPERTY_SETTER(NAME) \ - v8::Handle<v8::Value> V8Custom::v8##NAME##NamedPropertySetter( \ - v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) - -#define NAMED_PROPERTY_DELETER(NAME) \ - v8::Handle<v8::Boolean> V8Custom::v8##NAME##NamedPropertyDeleter( \ - v8::Local<v8::String> name, const v8::AccessorInfo& info) - -#define NAMED_ACCESS_CHECK(NAME) \ - bool V8Custom::v8##NAME##NamedSecurityCheck(v8::Local<v8::Object> host, \ - v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value> data) - -#define INDEXED_ACCESS_CHECK(NAME) \ - bool V8Custom::v8##NAME##IndexedSecurityCheck(v8::Local<v8::Object> host, \ - uint32_t index, v8::AccessType type, v8::Local<v8::Value> data) - -#define ACCESSOR_RUNTIME_ENABLER(NAME) bool V8Custom::v8##NAME##Enabled() - namespace WebCore { - - class DOMWindow; - class Element; - class Frame; - class HTMLCollection; - class HTMLFrameElementBase; - class String; - class V8Proxy; - - bool allowSettingFrameSrcToJavascriptUrl(HTMLFrameElementBase*, String value); - bool allowSettingSrcToJavascriptURL(Element*, String name, String value); - class V8Custom { public: - // Constants. - static const int kDOMWrapperTypeIndex = 0; - static const int kDOMWrapperObjectIndex = 1; - static const int kDefaultWrapperInternalFieldCount = 2; - - static const int kNPObjectInternalFieldCount = kDefaultWrapperInternalFieldCount + 0; - - static const int kNodeEventListenerCacheIndex = kDefaultWrapperInternalFieldCount + 0; - static const int kNodeMinimumInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; - - static const int kDocumentImplementationIndex = kNodeMinimumInternalFieldCount + 0; - static const int kDocumentMinimumInternalFieldCount = kNodeMinimumInternalFieldCount + 1; - - static const int kHTMLDocumentMarkerIndex = kDocumentMinimumInternalFieldCount + 0; - static const int kHTMLDocumentShadowIndex = kDocumentMinimumInternalFieldCount + 1; - static const int kHTMLDocumentInternalFieldCount = kDocumentMinimumInternalFieldCount + 2; - - static const int kXMLHttpRequestCacheIndex = kDefaultWrapperInternalFieldCount + 0; - static const int kXMLHttpRequestInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; - - static const int kMessageChannelPort1Index = kDefaultWrapperInternalFieldCount + 0; - static const int kMessageChannelPort2Index = kDefaultWrapperInternalFieldCount + 1; - static const int kMessageChannelInternalFieldCount = kDefaultWrapperInternalFieldCount + 2; - - static const int kMessagePortRequestCacheIndex = kDefaultWrapperInternalFieldCount + 0; - static const int kMessagePortInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; - -#if ENABLE(WORKERS) - static const int kAbstractWorkerRequestCacheIndex = kDefaultWrapperInternalFieldCount + 0; - static const int kAbstractWorkerInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; - - static const int kWorkerRequestCacheIndex = kAbstractWorkerInternalFieldCount + 0; - static const int kWorkerInternalFieldCount = kAbstractWorkerInternalFieldCount + 1; - - static const int kWorkerContextRequestCacheIndex = kDefaultWrapperInternalFieldCount + 0; - static const int kWorkerContextMinimumInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; - - static const int kDedicatedWorkerContextRequestCacheIndex = kWorkerContextMinimumInternalFieldCount + 0; - static const int kDedicatedWorkerContextInternalFieldCount = kWorkerContextMinimumInternalFieldCount + 1; -#endif - -#if ENABLE(SHARED_WORKERS) - static const int kSharedWorkerRequestCacheIndex = kAbstractWorkerInternalFieldCount + 0; - static const int kSharedWorkerInternalFieldCount = kAbstractWorkerInternalFieldCount + 1; - - static const int kSharedWorkerContextRequestCacheIndex = kWorkerContextMinimumInternalFieldCount + 0; - static const int kSharedWorkerContextInternalFieldCount = kWorkerContextMinimumInternalFieldCount + 1; -#endif - -#if ENABLE(NOTIFICATIONS) - static const int kNotificationRequestCacheIndex = kDefaultWrapperInternalFieldCount + 0; - static const int kNotificationInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; -#endif - -#if ENABLE(SVG) - static const int kSVGElementInstanceEventListenerCacheIndex = kDefaultWrapperInternalFieldCount + 0; - static const int kSVGElementInstanceInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; -#endif - - static const int kDOMWindowConsoleIndex = kDefaultWrapperInternalFieldCount + 0; - static const int kDOMWindowHistoryIndex = kDefaultWrapperInternalFieldCount + 1; - static const int kDOMWindowLocationbarIndex = kDefaultWrapperInternalFieldCount + 2; - static const int kDOMWindowMenubarIndex = kDefaultWrapperInternalFieldCount + 3; - static const int kDOMWindowNavigatorIndex = kDefaultWrapperInternalFieldCount + 4; - static const int kDOMWindowPersonalbarIndex = kDefaultWrapperInternalFieldCount + 5; - static const int kDOMWindowScreenIndex = kDefaultWrapperInternalFieldCount + 6; - static const int kDOMWindowScrollbarsIndex = kDefaultWrapperInternalFieldCount + 7; - static const int kDOMWindowSelectionIndex = kDefaultWrapperInternalFieldCount + 8; - static const int kDOMWindowStatusbarIndex = kDefaultWrapperInternalFieldCount + 9; - static const int kDOMWindowToolbarIndex = kDefaultWrapperInternalFieldCount + 10; - static const int kDOMWindowLocationIndex = kDefaultWrapperInternalFieldCount + 11; - static const int kDOMWindowDOMSelectionIndex = kDefaultWrapperInternalFieldCount + 12; - static const int kDOMWindowEventListenerCacheIndex = kDefaultWrapperInternalFieldCount + 13; - static const int kDOMWindowEnteredIsolatedWorldIndex = kDefaultWrapperInternalFieldCount + 14; - static const int kDOMWindowInternalFieldCount = kDefaultWrapperInternalFieldCount + 15; - - static const int kStyleSheetOwnerNodeIndex = kDefaultWrapperInternalFieldCount + 0; - static const int kStyleSheetInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; - static const int kNamedNodeMapOwnerNodeIndex = kDefaultWrapperInternalFieldCount + 0; - static const int kNamedNodeMapInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - static const int kDOMApplicationCacheCacheIndex = kDefaultWrapperInternalFieldCount + 0; - static const int kDOMApplicationCacheFieldCount = kDefaultWrapperInternalFieldCount + 1; -#endif - -#if ENABLE(WEB_SOCKETS) - static const int kWebSocketCacheIndex = kDefaultWrapperInternalFieldCount + 0; - static const int kWebSocketInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; -#endif - -#define DECLARE_PROPERTY_ACCESSOR_GETTER(NAME) \ - static v8::Handle<v8::Value> v8##NAME##AccessorGetter( \ - v8::Local<v8::String> name, const v8::AccessorInfo& info) - -#define DECLARE_PROPERTY_ACCESSOR_SETTER(NAME) \ - static void v8##NAME##AccessorSetter(v8::Local<v8::String> name, \ - v8::Local<v8::Value> value, const v8::AccessorInfo& info) - -#define DECLARE_PROPERTY_ACCESSOR(NAME) DECLARE_PROPERTY_ACCESSOR_GETTER(NAME); DECLARE_PROPERTY_ACCESSOR_SETTER(NAME) - -#define DECLARE_NAMED_PROPERTY_GETTER(NAME) \ - static v8::Handle<v8::Value> v8##NAME##NamedPropertyGetter( \ - v8::Local<v8::String> name, const v8::AccessorInfo& info) - -#define DECLARE_NAMED_PROPERTY_SETTER(NAME) \ - static v8::Handle<v8::Value> v8##NAME##NamedPropertySetter( \ - v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) - -#define DECLARE_NAMED_PROPERTY_DELETER(NAME) \ - static v8::Handle<v8::Boolean> v8##NAME##NamedPropertyDeleter( \ - v8::Local<v8::String> name, const v8::AccessorInfo& info) - -#define USE_NAMED_PROPERTY_GETTER(NAME) V8Custom::v8##NAME##NamedPropertyGetter - -#define USE_NAMED_PROPERTY_SETTER(NAME) V8Custom::v8##NAME##NamedPropertySetter - -#define USE_NAMED_PROPERTY_DELETER(NAME) V8Custom::v8##NAME##NamedPropertyDeleter - -#define DECLARE_INDEXED_PROPERTY_GETTER(NAME) \ - static v8::Handle<v8::Value> v8##NAME##IndexedPropertyGetter( \ - uint32_t index, const v8::AccessorInfo& info) - -#define DECLARE_INDEXED_PROPERTY_SETTER(NAME) \ - static v8::Handle<v8::Value> v8##NAME##IndexedPropertySetter( \ - uint32_t index, v8::Local<v8::Value> value, const v8::AccessorInfo& info) - -#define DECLARE_INDEXED_PROPERTY_DELETER(NAME) \ - static v8::Handle<v8::Boolean> v8##NAME##IndexedPropertyDeleter( \ - uint32_t index, const v8::AccessorInfo& info) - -#define USE_INDEXED_PROPERTY_GETTER(NAME) V8Custom::v8##NAME##IndexedPropertyGetter - -#define USE_INDEXED_PROPERTY_SETTER(NAME) V8Custom::v8##NAME##IndexedPropertySetter - -#define USE_INDEXED_PROPERTY_DELETER(NAME) V8Custom::v8##NAME##IndexedPropertyDeleter - #define DECLARE_CALLBACK(NAME) static v8::Handle<v8::Value> v8##NAME##Callback(const v8::Arguments& args) - #define USE_CALLBACK(NAME) V8Custom::v8##NAME##Callback -#define DECLARE_NAMED_ACCESS_CHECK(NAME) \ - static bool v8##NAME##NamedSecurityCheck(v8::Local<v8::Object> host, \ - v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value> data) - -#define DECLARE_INDEXED_ACCESS_CHECK(NAME) \ - static bool v8##NAME##IndexedSecurityCheck(v8::Local<v8::Object> host, \ - uint32_t index, v8::AccessType type, v8::Local<v8::Value> data) - -#define DECLARE_ACCESSOR_RUNTIME_ENABLER(NAME) static bool v8##NAME##Enabled() - - DECLARE_PROPERTY_ACCESSOR(CanvasRenderingContext2DStrokeStyle); - DECLARE_PROPERTY_ACCESSOR(CanvasRenderingContext2DFillStyle); - DECLARE_PROPERTY_ACCESSOR(DOMWindowEvent); - DECLARE_PROPERTY_ACCESSOR_GETTER(DOMWindowCrypto); - DECLARE_PROPERTY_ACCESSOR_SETTER(DOMWindowLocation); - DECLARE_PROPERTY_ACCESSOR_SETTER(DOMWindowOpener); - -#if ENABLE(VIDEO) - DECLARE_PROPERTY_ACCESSOR_GETTER(DOMWindowAudio); - DECLARE_ACCESSOR_RUNTIME_ENABLER(DOMWindowAudio); - DECLARE_ACCESSOR_RUNTIME_ENABLER(DOMWindowHTMLMediaElement); - DECLARE_ACCESSOR_RUNTIME_ENABLER(DOMWindowHTMLAudioElement); - DECLARE_ACCESSOR_RUNTIME_ENABLER(DOMWindowHTMLVideoElement); - DECLARE_ACCESSOR_RUNTIME_ENABLER(DOMWindowMediaError); -#endif - - DECLARE_PROPERTY_ACCESSOR_GETTER(DOMWindowImage); - DECLARE_PROPERTY_ACCESSOR_GETTER(DOMWindowOption); - - DECLARE_PROPERTY_ACCESSOR(DocumentLocation); - DECLARE_PROPERTY_ACCESSOR(DocumentImplementation); - DECLARE_PROPERTY_ACCESSOR_GETTER(EventSrcElement); - DECLARE_PROPERTY_ACCESSOR(EventReturnValue); - DECLARE_PROPERTY_ACCESSOR_GETTER(EventDataTransfer); - DECLARE_PROPERTY_ACCESSOR_GETTER(EventClipboardData); - - DECLARE_PROPERTY_ACCESSOR(DOMWindowEventHandler); - - DECLARE_CALLBACK(HTMLCanvasElementGetContext); - - DECLARE_PROPERTY_ACCESSOR_SETTER(HTMLFrameElementSrc); - DECLARE_PROPERTY_ACCESSOR_SETTER(HTMLFrameElementLocation); - DECLARE_PROPERTY_ACCESSOR_SETTER(HTMLIFrameElementSrc); - - DECLARE_PROPERTY_ACCESSOR_SETTER(AttrValue); - - DECLARE_PROPERTY_ACCESSOR(HTMLOptionsCollectionLength); - - DECLARE_CALLBACK(HTMLInputElementSetSelectionRange); - - DECLARE_PROPERTY_ACCESSOR(HTMLInputElementSelectionStart); - DECLARE_PROPERTY_ACCESSOR(HTMLInputElementSelectionEnd); - - DECLARE_NAMED_ACCESS_CHECK(Location); - DECLARE_INDEXED_ACCESS_CHECK(History); - - DECLARE_NAMED_ACCESS_CHECK(History); - DECLARE_INDEXED_ACCESS_CHECK(Location); - - DECLARE_CALLBACK(HTMLCollectionItem); - DECLARE_CALLBACK(HTMLCollectionNamedItem); - DECLARE_CALLBACK(HTMLCollectionCallAsFunction); - - DECLARE_CALLBACK(HTMLAllCollectionItem); - DECLARE_CALLBACK(HTMLAllCollectionNamedItem); - DECLARE_CALLBACK(HTMLAllCollectionCallAsFunction); - - DECLARE_CALLBACK(HTMLSelectElementRemove); - - DECLARE_CALLBACK(HTMLOptionsCollectionRemove); - DECLARE_CALLBACK(HTMLOptionsCollectionAdd); - - DECLARE_CALLBACK(HTMLDocumentWrite); - DECLARE_CALLBACK(HTMLDocumentWriteln); - DECLARE_CALLBACK(HTMLDocumentOpen); - DECLARE_PROPERTY_ACCESSOR(HTMLDocumentAll); - DECLARE_NAMED_PROPERTY_GETTER(HTMLDocument); - DECLARE_NAMED_PROPERTY_DELETER(HTMLDocument); - - DECLARE_CALLBACK(DocumentEvaluate); - DECLARE_CALLBACK(DocumentGetCSSCanvasContext); - - DECLARE_CALLBACK(DOMWindowAddEventListener); - DECLARE_CALLBACK(DOMWindowRemoveEventListener); - DECLARE_CALLBACK(DOMWindowPostMessage); - DECLARE_CALLBACK(DOMWindowSetTimeout); - DECLARE_CALLBACK(DOMWindowSetInterval); - DECLARE_CALLBACK(DOMWindowAtob); - DECLARE_CALLBACK(DOMWindowBtoa); - DECLARE_CALLBACK(DOMWindowNOP); - DECLARE_CALLBACK(DOMWindowToString); - DECLARE_CALLBACK(DOMWindowShowModalDialog); - DECLARE_CALLBACK(DOMWindowOpen); - DECLARE_CALLBACK(DOMWindowClearTimeout); - DECLARE_CALLBACK(DOMWindowClearInterval); - - DECLARE_CALLBACK(DOMParserConstructor); DECLARE_CALLBACK(HTMLAudioElementConstructor); DECLARE_CALLBACK(HTMLImageElementConstructor); DECLARE_CALLBACK(HTMLOptionElementConstructor); +<<<<<<< HEAD DECLARE_CALLBACK(MessageChannelConstructor); DECLARE_CALLBACK(WebKitCSSMatrixConstructor); DECLARE_CALLBACK(WebKitPointConstructor); @@ -714,27 +422,11 @@ namespace WebCore { #undef DECLARE_INDEXED_PROPERTY_GETTER #undef DECLARE_INDEXED_PROPERTY_SETTER #undef DECLARE_INDEXED_PROPERTY_DELETER +======= +>>>>>>> webkit.org at r54127 #undef DECLARE_CALLBACK - - // Returns the NPObject corresponding to an HTMLElement object. - static NPObject* GetHTMLPlugInElementNPObject(v8::Handle<v8::Object>); - - // Returns the owner frame pointer of a DOM wrapper object. It only works for - // these DOM objects requiring cross-domain access check. - static Frame* GetTargetFrame(v8::Local<v8::Object> host, v8::Local<v8::Value> data); - - // Special case for downcasting SVG path segments. -#if ENABLE(SVG) - static V8ClassIndex::V8WrapperType DowncastSVGPathSeg(void* pathSeg); -#endif - - private: - static v8::Handle<v8::Value> WindowSetTimeoutImpl(const v8::Arguments&, bool singleShot); - static void ClearTimeoutImpl(const v8::Arguments&); - static void WindowSetLocation(DOMWindow*, const String&); }; - } // namespace WebCore #endif // V8CustomBinding_h diff --git a/WebCore/bindings/v8/custom/V8DOMApplicationCacheCustom.cpp b/WebCore/bindings/v8/custom/V8DOMApplicationCacheCustom.cpp index 134de95..a439432 100644 --- a/WebCore/bindings/v8/custom/V8DOMApplicationCacheCustom.cpp +++ b/WebCore/bindings/v8/custom/V8DOMApplicationCacheCustom.cpp @@ -29,11 +29,12 @@ */ #include "config.h" -#include "DOMApplicationCache.h" +#include "V8DOMApplicationCache.h" #if ENABLE(OFFLINE_WEB_APPLICATIONS) #include "ApplicationCacheHost.h" +#include "DOMApplicationCache.h" #include "V8Binding.h" #include "V8CustomBinding.h" #include "V8Document.h" @@ -44,14 +45,14 @@ namespace WebCore { // Handles appcache.addEventListner(name, func, capture) method calls -CALLBACK_FUNC_DECL(DOMApplicationCacheAddEventListener) +v8::Handle<v8::Value> V8DOMApplicationCache::addEventListenerCallback(const v8::Arguments& args) { INC_STATS("DOMApplicationCache.addEventListener()"); - DOMApplicationCache* appcache = V8DOMWrapper::convertToNativeObject<DOMApplicationCache>(V8ClassIndex::DOMAPPLICATIONCACHE, args.Holder()); + DOMApplicationCache* appcache = V8DOMApplicationCache::toNative(args.Holder()); RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(appcache, args[1], false, ListenerFindOrCreate); if (listener) { - createHiddenDependency(args.Holder(), args[1], V8Custom::kDOMApplicationCacheCacheIndex); + createHiddenDependency(args.Holder(), args[1], cacheIndex); String eventType = toWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); appcache->addEventListener(eventType, listener, useCapture); @@ -60,14 +61,14 @@ CALLBACK_FUNC_DECL(DOMApplicationCacheAddEventListener) } // Handles appcache.removeEventListner(name, func, capture) method calls -CALLBACK_FUNC_DECL(DOMApplicationCacheRemoveEventListener) +v8::Handle<v8::Value> V8DOMApplicationCache::removeEventListenerCallback(const v8::Arguments& args) { INC_STATS("DOMApplicationCache.removeEventListener()"); - DOMApplicationCache* appcache = V8DOMWrapper::convertToNativeObject<DOMApplicationCache>(V8ClassIndex::DOMAPPLICATIONCACHE, args.Holder()); + DOMApplicationCache* appcache = V8DOMApplicationCache::toNative(args.Holder()); RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(appcache, args[1], false, ListenerFindOnly); if (listener) { - removeHiddenDependency(args.Holder(), args[1], V8Custom::kDOMApplicationCacheCacheIndex); + removeHiddenDependency(args.Holder(), args[1], cacheIndex); String eventType = toWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); appcache->removeEventListener(eventType, listener.get(), useCapture); diff --git a/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp b/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp index 46c33b9..2933b4d 100644 --- a/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp +++ b/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp @@ -29,22 +29,19 @@ */ #include "config.h" -#include "DOMWindow.h" - -#include "V8Binding.h" -#include "V8CustomBinding.h" -#include "V8CustomEventListener.h" -#include "V8MessagePortCustom.h" -#include "V8Proxy.h" -#include "V8Utilities.h" +#include "V8DOMWindow.h" #include "Base64.h" -#include "ExceptionCode.h" +#include "Chrome.h" +#include "Database.h" #include "DOMTimer.h" +#include "DOMWindow.h" +#include "ExceptionCode.h" #include "Frame.h" #include "FrameLoadRequest.h" #include "FrameView.h" #include "HTMLCollection.h" +#include "HTMLDocument.h" #include "MediaPlayer.h" #include "Page.h" #include "PlatformScreen.h" @@ -55,6 +52,14 @@ #include "Settings.h" #include "SharedWorkerRepository.h" #include "Storage.h" +#include "V8Binding.h" +#include "V8BindingDOMWindow.h" +#include "V8BindingState.h" +#include "V8CustomBinding.h" +#include "V8CustomEventListener.h" +#include "V8MessagePortCustom.h" +#include "V8Proxy.h" +#include "V8Utilities.h" #if ENABLE(WEB_SOCKETS) #include "WebSocket.h" #endif @@ -66,7 +71,7 @@ static const int popupTilePixels = 10; namespace WebCore { -v8::Handle<v8::Value> V8Custom::WindowSetTimeoutImpl(const v8::Arguments& args, bool singleShot) +v8::Handle<v8::Value> WindowSetTimeoutImpl(const v8::Arguments& args, bool singleShot) { int argumentCount = args.Length(); @@ -99,9 +104,9 @@ v8::Handle<v8::Value> V8Custom::WindowSetTimeoutImpl(const v8::Arguments& args, if (argumentCount >= 2) timeout = args[1]->Int32Value(); - DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); + DOMWindow* imp = V8DOMWindow::toNative(args.Holder()); - if (!V8Proxy::canAccessFrame(imp->frame(), true)) + if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true)) return v8::Undefined(); ScriptExecutionContext* scriptContext = static_cast<ScriptExecutionContext*>(imp->document()); @@ -164,14 +169,14 @@ static v8::Handle<v8::Value> convertBase64(const String& str, bool encode) return v8String(String(outputCharacters.data(), outputCharacters.size())); } -ACCESSOR_GETTER(DOMWindowEvent) +v8::Handle<v8::Value> V8DOMWindow::eventAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This()); if (holder.IsEmpty()) return v8::Undefined(); - Frame* frame = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder)->frame(); - if (!V8Proxy::canAccessFrame(frame, true)) + Frame* frame = V8DOMWindow::toNative(holder)->frame(); + if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), frame, true)) return v8::Undefined(); v8::Local<v8::Context> context = V8Proxy::context(frame); @@ -185,14 +190,14 @@ ACCESSOR_GETTER(DOMWindowEvent) return jsEvent; } -ACCESSOR_SETTER(DOMWindowEvent) +void V8DOMWindow::eventAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This()); if (holder.IsEmpty()) return; - Frame* frame = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder)->frame(); - if (!V8Proxy::canAccessFrame(frame, true)) + Frame* frame = V8DOMWindow::toNative(holder)->frame(); + if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), frame, true)) return; v8::Local<v8::Context> context = V8Proxy::context(frame); @@ -203,24 +208,24 @@ ACCESSOR_SETTER(DOMWindowEvent) context->Global()->SetHiddenValue(eventSymbol, value); } -ACCESSOR_GETTER(DOMWindowCrypto) +v8::Handle<v8::Value> V8DOMWindow::cryptoAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { // FIXME: Implement me. return v8::Undefined(); } -ACCESSOR_SETTER(DOMWindowLocation) +void V8DOMWindow::locationAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { - DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, info.Holder()); - WindowSetLocation(imp, toWebCoreString(value)); + DOMWindow* imp = V8DOMWindow::toNative(info.Holder()); + V8DOMWindowShell::setLocation(imp, toWebCoreString(value)); } -ACCESSOR_SETTER(DOMWindowOpener) +void V8DOMWindow::openerAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { - DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, info.Holder()); + DOMWindow* imp = V8DOMWindow::toNative(info.Holder()); - if (!V8Proxy::canAccessFrame(imp->frame(), true)) + if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true)) return; // Opener can be shadowed if it is in the same domain. @@ -242,33 +247,33 @@ ACCESSOR_SETTER(DOMWindowOpener) #if ENABLE(VIDEO) -ACCESSOR_GETTER(DOMWindowAudio) +v8::Handle<v8::Value> V8DOMWindow::AudioAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { - DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, info.Holder()); + DOMWindow* window = V8DOMWindow::toNative(info.Holder()); return V8DOMWrapper::getConstructor(V8ClassIndex::AUDIO, window); } -ACCESSOR_RUNTIME_ENABLER(DOMWindowAudio) +bool V8DOMWindow::AudioEnabled() { return MediaPlayer::isAvailable(); } -ACCESSOR_RUNTIME_ENABLER(DOMWindowHTMLMediaElement) +bool V8DOMWindow::HTMLMediaElementEnabled() { return MediaPlayer::isAvailable(); } -ACCESSOR_RUNTIME_ENABLER(DOMWindowHTMLAudioElement) +bool V8DOMWindow::HTMLAudioElementEnabled() { return MediaPlayer::isAvailable(); } -ACCESSOR_RUNTIME_ENABLER(DOMWindowHTMLVideoElement) +bool V8DOMWindow::HTMLVideoElementEnabled() { return MediaPlayer::isAvailable(); } -ACCESSOR_RUNTIME_ENABLER(DOMWindowMediaError) +bool V8DOMWindow::MediaErrorEnabled() { return MediaPlayer::isAvailable(); } @@ -276,74 +281,81 @@ ACCESSOR_RUNTIME_ENABLER(DOMWindowMediaError) #endif #if ENABLE(SHARED_WORKERS) -ACCESSOR_RUNTIME_ENABLER(DOMWindowSharedWorker) +bool V8DOMWindow::SharedWorkerEnabled() { return SharedWorkerRepository::isAvailable(); } #endif #if ENABLE(WEB_SOCKETS) -ACCESSOR_RUNTIME_ENABLER(DOMWindowWebSocket) +bool V8DOMWindow::WebSocketEnabled() { return WebSocket::isAvailable(); } #endif #if ENABLE(DATABASE) -ACCESSOR_RUNTIME_ENABLER(DOMWindowOpenDatabase) +bool V8DOMWindow::OpenDatabaseEnabled() +{ + return Database::isAvailable(); +} +#endif + +#if ENABLE(INDEXED_DATABASE) +bool V8DOMWindow::IndexedDBEnabled() { - return WebCore::RuntimeEnabledFeatures::databaseEnabled(); + return RuntimeEnabledFeatures::indexedDatabaseEnabled(); } #endif #if ENABLE(DOM_STORAGE) -ACCESSOR_RUNTIME_ENABLER(DOMWindowLocalStorage) +bool V8DOMWindow::LocalStorageEnabled() { return RuntimeEnabledFeatures::localStorageEnabled(); } -ACCESSOR_RUNTIME_ENABLER(DOMWindowSessionStorage) +bool V8DOMWindow::SessionStorageEnabled() { return RuntimeEnabledFeatures::sessionStorageEnabled(); } #endif #if ENABLE(NOTIFICATIONS) -ACCESSOR_RUNTIME_ENABLER(DOMWindowWebkitNotifications) +bool V8DOMWindow::WebkitNotificationsEnabled() { return RuntimeEnabledFeatures::notificationsEnabled(); } #endif #if ENABLE(OFFLINE_WEB_APPLICATIONS) -ACCESSOR_RUNTIME_ENABLER(DOMWindowApplicationCache) +bool V8DOMWindow::ApplicationCacheEnabled() { return RuntimeEnabledFeatures::applicationCacheEnabled(); } #endif -ACCESSOR_GETTER(DOMWindowImage) +v8::Handle<v8::Value> V8DOMWindow::ImageAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { - DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, info.Holder()); + DOMWindow* window = V8DOMWindow::toNative(info.Holder()); return V8DOMWrapper::getConstructor(V8ClassIndex::IMAGE, window); } -ACCESSOR_GETTER(DOMWindowOption) +v8::Handle<v8::Value> V8DOMWindow::OptionAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { - DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, info.Holder()); + DOMWindow* window = V8DOMWindow::toNative(info.Holder()); return V8DOMWrapper::getConstructor(V8ClassIndex::OPTION, window); } -CALLBACK_FUNC_DECL(DOMWindowAddEventListener) +v8::Handle<v8::Value> V8DOMWindow::addEventListenerCallback(const v8::Arguments& args) { INC_STATS("DOM.DOMWindow.addEventListener()"); String eventType = toWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); - DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); + DOMWindow* imp = V8DOMWindow::toNative(args.Holder()); - if (!V8Proxy::canAccessFrame(imp->frame(), true)) + if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true)) return v8::Undefined(); Document* doc = imp->document(); @@ -360,23 +372,23 @@ CALLBACK_FUNC_DECL(DOMWindowAddEventListener) if (listener) { imp->addEventListener(eventType, listener, useCapture); - createHiddenDependency(args.Holder(), args[1], V8Custom::kDOMWindowEventListenerCacheIndex); + createHiddenDependency(args.Holder(), args[1], cacheIndex); } return v8::Undefined(); } -CALLBACK_FUNC_DECL(DOMWindowRemoveEventListener) +v8::Handle<v8::Value> V8DOMWindow::removeEventListenerCallback(const v8::Arguments& args) { INC_STATS("DOM.DOMWindow.removeEventListener()"); String eventType = toWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); - DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); + DOMWindow* imp = V8DOMWindow::toNative(args.Holder()); - if (!V8Proxy::canAccessFrame(imp->frame(), true)) + if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true)) return v8::Undefined(); Document* doc = imp->document(); @@ -392,22 +404,22 @@ CALLBACK_FUNC_DECL(DOMWindowRemoveEventListener) if (listener) { imp->removeEventListener(eventType, listener.get(), useCapture); - removeHiddenDependency(args.Holder(), args[1], V8Custom::kDOMWindowEventListenerCacheIndex); + removeHiddenDependency(args.Holder(), args[1], cacheIndex); } return v8::Undefined(); } -CALLBACK_FUNC_DECL(DOMWindowPostMessage) +v8::Handle<v8::Value> V8DOMWindow::postMessageCallback(const v8::Arguments& args) { INC_STATS("DOM.DOMWindow.postMessage()"); - DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); + DOMWindow* window = V8DOMWindow::toNative(args.Holder()); DOMWindow* source = V8Proxy::retrieveFrameForCallingContext()->domWindow(); ASSERT(source->frame()); v8::TryCatch tryCatch; - RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(toWebCoreString(args[0])); + RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(args[0]); MessagePortArray portArray; String targetOrigin; @@ -431,7 +443,7 @@ CALLBACK_FUNC_DECL(DOMWindowPostMessage) return throwError(ec); } -CALLBACK_FUNC_DECL(DOMWindowAtob) +v8::Handle<v8::Value> V8DOMWindow::atobCallback(const v8::Arguments& args) { INC_STATS("DOM.DOMWindow.atob()"); @@ -439,9 +451,9 @@ CALLBACK_FUNC_DECL(DOMWindowAtob) return v8String(""); String str = toWebCoreString(args[0]); - DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); + DOMWindow* imp = V8DOMWindow::toNative(args.Holder()); - if (!V8Proxy::canAccessFrame(imp->frame(), true)) + if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true)) return v8::Undefined(); if (args.Length() < 1) @@ -450,7 +462,7 @@ CALLBACK_FUNC_DECL(DOMWindowAtob) return convertBase64(str, false); } -CALLBACK_FUNC_DECL(DOMWindowBtoa) +v8::Handle<v8::Value> V8DOMWindow::btoaCallback(const v8::Arguments& args) { INC_STATS("DOM.DOMWindow.btoa()"); @@ -458,9 +470,9 @@ CALLBACK_FUNC_DECL(DOMWindowBtoa) return v8String(""); String str = toWebCoreString(args[0]); - DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); + DOMWindow* imp = V8DOMWindow::toNative(args.Holder()); - if (!V8Proxy::canAccessFrame(imp->frame(), true)) + if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true)) return v8::Undefined(); if (args.Length() < 1) @@ -473,7 +485,7 @@ CALLBACK_FUNC_DECL(DOMWindowBtoa) // fix this by calling toString function on the receiver. // However, V8 implements toString in JavaScript, which requires // switching context of receiver. I consider it is dangerous. -CALLBACK_FUNC_DECL(DOMWindowToString) +v8::Handle<v8::Value> V8DOMWindow::toStringCallback(const v8::Arguments& args) { INC_STATS("DOM.DOMWindow.toString()"); v8::Handle<v8::Object> domWrapper = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, args.This()); @@ -482,7 +494,13 @@ CALLBACK_FUNC_DECL(DOMWindowToString) return domWrapper->ObjectProtoToString(); } -CALLBACK_FUNC_DECL(DOMWindowNOP) +v8::Handle<v8::Value> V8DOMWindow::releaseEventsCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.DOMWindow.nop()"); + return v8::Undefined(); +} + +v8::Handle<v8::Value> V8DOMWindow::captureEventsCallback(const v8::Arguments& args) { INC_STATS("DOM.DOMWindow.nop()"); return v8::Undefined(); @@ -538,78 +556,7 @@ static HashMap<String, String> parseModalDialogFeatures(const String& featuresAr return map; } - -static Frame* createWindow(Frame* callingFrame, - Frame* enteredFrame, - Frame* openerFrame, - const String& url, - const String& frameName, - const WindowFeatures& windowFeatures, - v8::Local<v8::Value> dialogArgs) -{ - ASSERT(callingFrame); - ASSERT(enteredFrame); - - // Sandboxed iframes cannot open new auxiliary browsing contexts. - if (callingFrame && callingFrame->loader()->isSandboxed(SandboxNavigation)) - return 0; - - ResourceRequest request; - - // For whatever reason, Firefox uses the entered frame to determine - // the outgoingReferrer. We replicate that behavior here. - String referrer = enteredFrame->loader()->outgoingReferrer(); - request.setHTTPReferrer(referrer); - FrameLoader::addHTTPOriginIfNeeded(request, enteredFrame->loader()->outgoingOrigin()); - FrameLoadRequest frameRequest(request, frameName); - - // FIXME: It's much better for client API if a new window starts with a URL, - // here where we know what URL we are going to open. Unfortunately, this - // code passes the empty string for the URL, but there's a reason for that. - // Before loading we have to set up the opener, openedByDOM, - // and dialogArguments values. Also, to decide whether to use the URL - // we currently do an allowsAccessFrom call using the window we create, - // which can't be done before creating it. We'd have to resolve all those - // issues to pass the URL instead of "". - - bool created; - // We pass in the opener frame here so it can be used for looking up the - // frame name, in case the active frame is different from the opener frame, - // and the name references a frame relative to the opener frame, for example - // "_self" or "_parent". - Frame* newFrame = callingFrame->loader()->createWindow(openerFrame->loader(), frameRequest, windowFeatures, created); - if (!newFrame) - return 0; - - newFrame->loader()->setOpener(openerFrame); - newFrame->page()->setOpenedByDOM(); - - // Set dialog arguments on the global object of the new frame. - if (!dialogArgs.IsEmpty()) { - v8::Local<v8::Context> context = V8Proxy::context(newFrame); - if (!context.IsEmpty()) { - v8::Context::Scope scope(context); - context->Global()->Set(v8::String::New("dialogArguments"), dialogArgs); - } - } - - if (protocolIsJavaScript(url) || ScriptController::isSafeScript(newFrame)) { - KURL completedUrl = - url.isEmpty() ? KURL(ParsedURLString, "") : completeURL(url); - bool userGesture = processingUserGesture(); - - if (created) - newFrame->loader()->changeLocation(completedUrl, referrer, false, false, userGesture); - else if (!url.isEmpty()) - newFrame->redirectScheduler()->scheduleLocationChange(completedUrl.string(), referrer, false, userGesture); - } - - return newFrame; -} - - - -CALLBACK_FUNC_DECL(DOMWindowShowModalDialog) +v8::Handle<v8::Value> V8DOMWindow::showModalDialogCallback(const v8::Arguments& args) { INC_STATS("DOM.DOMWindow.showModalDialog()"); @@ -617,11 +564,10 @@ CALLBACK_FUNC_DECL(DOMWindowShowModalDialog) v8::Local<v8::Value> dialogArgs = args[1]; String featureArgs = toWebCoreStringWithNullOrUndefinedCheck(args[2]); - DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>( - V8ClassIndex::DOMWINDOW, args.Holder()); + DOMWindow* window = V8DOMWindow::toNative(args.Holder()); Frame* frame = window->frame(); - if (!V8Proxy::canAccessFrame(frame, true)) + if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), frame, true)) return v8::Undefined(); Frame* callingFrame = V8Proxy::retrieveFrameForCallingContext(); @@ -674,7 +620,7 @@ CALLBACK_FUNC_DECL(DOMWindowShowModalDialog) windowFeatures.locationBarVisible = false; windowFeatures.fullscreen = false; - Frame* dialogFrame = createWindow(callingFrame, enteredFrame, frame, url, "", windowFeatures, dialogArgs); + Frame* dialogFrame = V8BindingDOMWindow::createWindow(V8BindingState::Only(), callingFrame, enteredFrame, frame, url, "", windowFeatures, dialogArgs); if (!dialogFrame) return v8::Undefined(); @@ -699,17 +645,17 @@ CALLBACK_FUNC_DECL(DOMWindowShowModalDialog) } -CALLBACK_FUNC_DECL(DOMWindowOpen) +v8::Handle<v8::Value> V8DOMWindow::openCallback(const v8::Arguments& args) { INC_STATS("DOM.DOMWindow.open()"); String urlString = toWebCoreStringWithNullOrUndefinedCheck(args[0]); AtomicString frameName = (args[1]->IsUndefined() || args[1]->IsNull()) ? "_blank" : AtomicString(toWebCoreString(args[1])); - DOMWindow* parent = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); + DOMWindow* parent = V8DOMWindow::toNative(args.Holder()); Frame* frame = parent->frame(); - if (!V8Proxy::canAccessFrame(frame, true)) + if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), frame, true)) return v8::Undefined(); Frame* enteredFrame = V8Proxy::retrieveFrameForEnteredContext(); @@ -817,7 +763,7 @@ CALLBACK_FUNC_DECL(DOMWindowOpen) windowFeatures.ySet = false; } - frame = createWindow(callingFrame, enteredFrame, frame, urlString, frameName, windowFeatures, v8::Local<v8::Value>()); + frame = V8BindingDOMWindow::createWindow(V8BindingState::Only(), callingFrame, enteredFrame, frame, urlString, frameName, windowFeatures, v8::Local<v8::Value>()); if (!frame) return v8::Undefined(); @@ -826,11 +772,11 @@ CALLBACK_FUNC_DECL(DOMWindowOpen) } -INDEXED_PROPERTY_GETTER(DOMWindow) +v8::Handle<v8::Value> V8DOMWindow::indexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info) { INC_STATS("DOM.DOMWindow.IndexedPropertyGetter"); - DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, info.Holder()); + DOMWindow* window = V8DOMWindow::toNative(info.Holder()); if (!window) return notHandledByInterceptor(); @@ -846,12 +792,11 @@ INDEXED_PROPERTY_GETTER(DOMWindow) } -NAMED_PROPERTY_GETTER(DOMWindow) +v8::Handle<v8::Value> V8DOMWindow::namedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.DOMWindow.NamedPropertyGetter"); - // TODO(antonm): investigate what convertToNativeObject does for the case of DOMWINDOW. - DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, info.Holder()); + DOMWindow* window = V8DOMWindow::toNative(info.Holder()); if (!window) return notHandledByInterceptor(); @@ -874,13 +819,14 @@ NAMED_PROPERTY_GETTER(DOMWindow) // Search named items in the document. Document* doc = frame->document(); - if (doc) { - RefPtr<HTMLCollection> items = doc->windowNamedItems(propName); - if (items->length() >= 1) { - if (items->length() == 1) - return V8DOMWrapper::convertNodeToV8Object(items->firstItem()); - else + if (doc && doc->isHTMLDocument()) { + if (static_cast<HTMLDocument*>(doc)->hasNamedItem(propName.impl()) || doc->hasElementWithId(propName.impl())) { + RefPtr<HTMLCollection> items = doc->windowNamedItems(propName); + if (items->length() >= 1) { + if (items->length() == 1) + return V8DOMWrapper::convertNodeToV8Object(items->firstItem()); return V8DOMWrapper::convertToV8Object(V8ClassIndex::HTMLCOLLECTION, items.release()); + } } } @@ -888,44 +834,27 @@ NAMED_PROPERTY_GETTER(DOMWindow) } -void V8Custom::WindowSetLocation(DOMWindow* window, const String& relativeURL) -{ - Frame* frame = window->frame(); - if (!frame) - return; - - KURL url = completeURL(relativeURL); - if (url.isNull()) - return; - - if (!shouldAllowNavigation(frame)) - return; - - navigateIfAllowed(frame, url, false, false); -} - - -CALLBACK_FUNC_DECL(DOMWindowSetTimeout) +v8::Handle<v8::Value> V8DOMWindow::setTimeoutCallback(const v8::Arguments& args) { INC_STATS("DOM.DOMWindow.setTimeout()"); return WindowSetTimeoutImpl(args, true); } -CALLBACK_FUNC_DECL(DOMWindowSetInterval) +v8::Handle<v8::Value> V8DOMWindow::setIntervalCallback(const v8::Arguments& args) { INC_STATS("DOM.DOMWindow.setInterval()"); return WindowSetTimeoutImpl(args, false); } -void V8Custom::ClearTimeoutImpl(const v8::Arguments& args) +void ClearTimeoutImpl(const v8::Arguments& args) { int handle = toInt32(args[0]); v8::Handle<v8::Object> holder = args.Holder(); - DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder); - if (!V8Proxy::canAccessFrame(imp->frame(), true)) + DOMWindow* imp = V8DOMWindow::toNative(holder); + if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true)) return; ScriptExecutionContext* context = static_cast<ScriptExecutionContext*>(imp->document()); if (!context) @@ -934,28 +863,28 @@ void V8Custom::ClearTimeoutImpl(const v8::Arguments& args) } -CALLBACK_FUNC_DECL(DOMWindowClearTimeout) +v8::Handle<v8::Value> V8DOMWindow::clearTimeoutCallback(const v8::Arguments& args) { INC_STATS("DOM.DOMWindow.clearTimeout"); ClearTimeoutImpl(args); return v8::Undefined(); } -CALLBACK_FUNC_DECL(DOMWindowClearInterval) +v8::Handle<v8::Value> V8DOMWindow::clearIntervalCallback(const v8::Arguments& args) { INC_STATS("DOM.DOMWindow.clearInterval"); ClearTimeoutImpl(args); return v8::Undefined(); } -NAMED_ACCESS_CHECK(DOMWindow) +bool V8DOMWindow::namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value> data) { ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::DOMWINDOW); v8::Handle<v8::Object> window = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, host); if (window.IsEmpty()) return false; // the frame is gone. - DOMWindow* targetWindow = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, window); + DOMWindow* targetWindow = V8DOMWindow::toNative(window); ASSERT(targetWindow); @@ -971,17 +900,17 @@ NAMED_ACCESS_CHECK(DOMWindow) return true; } - return V8Proxy::canAccessFrame(target, false); + return V8BindingSecurity::canAccessFrame(V8BindingState::Only(), target, false); } -INDEXED_ACCESS_CHECK(DOMWindow) +bool V8DOMWindow::indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType type, v8::Local<v8::Value> data) { ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::DOMWINDOW); v8::Handle<v8::Object> window = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, host); if (window.IsEmpty()) return false; - DOMWindow* targetWindow = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, window); + DOMWindow* targetWindow = V8DOMWindow::toNative(window); ASSERT(targetWindow); @@ -993,7 +922,7 @@ INDEXED_ACCESS_CHECK(DOMWindow) if ((type == v8::ACCESS_GET || type == v8::ACCESS_HAS) && target->tree()->child(index)) return true; - return V8Proxy::canAccessFrame(target, false); + return V8BindingSecurity::canAccessFrame(V8BindingState::Only(), target, false); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8DataGridColumnListCustom.cpp b/WebCore/bindings/v8/custom/V8DataGridColumnListCustom.cpp index 1dde996..8980cfe 100644 --- a/WebCore/bindings/v8/custom/V8DataGridColumnListCustom.cpp +++ b/WebCore/bindings/v8/custom/V8DataGridColumnListCustom.cpp @@ -40,16 +40,6 @@ namespace WebCore { -INDEXED_PROPERTY_GETTER(DataGridColumnList) -{ - INC_STATS("DataGridColumnList.IndexedPropertyGetter"); - DataGridColumnList* imp = V8DOMWrapper::convertToNativeObject<DataGridColumnList>(V8ClassIndex::DATAGRIDCOLUMNLIST, info.Holder()); - DataGridColumn* result = imp->item(index); - if (!result) - return notHandledByInterceptor(); - return V8DOMWrapper::convertToV8Object(V8ClassIndex::DATAGRIDCOLUMN, result); -} - NAMED_PROPERTY_GETTER(DataGridColumnList) { INC_STATS("DataGridColumnList.NamedPropertyGetter"); @@ -63,7 +53,7 @@ NAMED_PROPERTY_GETTER(DataGridColumnList) return notHandledByInterceptor(); // Finally, look up a column by name. - DataGridColumnList* imp = V8DOMWrapper::convertToNativeObject<DataGridColumnList>(V8ClassIndex::DATAGRIDCOLUMNLIST, info.Holder()); + DataGridColumnList* imp = V8DataGridColumnList::toNative(info.Holder()); DataGridColumn* result = imp->itemWithName(toWebCoreString(name)); if (!result) return notHandledByInterceptor(); diff --git a/WebCore/bindings/v8/custom/V8DatabaseCustom.cpp b/WebCore/bindings/v8/custom/V8DatabaseCustom.cpp index 9ddd620..c83e1cc 100644 --- a/WebCore/bindings/v8/custom/V8DatabaseCustom.cpp +++ b/WebCore/bindings/v8/custom/V8DatabaseCustom.cpp @@ -31,6 +31,7 @@ #include "config.h" #if ENABLE(DATABASE) +#include "V8Database.h" #include "Database.h" #include "V8Binding.h" @@ -42,7 +43,7 @@ namespace WebCore { -CALLBACK_FUNC_DECL(DatabaseChangeVersion) +v8::Handle<v8::Value> V8Database::changeVersionCallback(const v8::Arguments& args) { INC_STATS("DOM.Database.changeVersion()"); @@ -52,7 +53,7 @@ CALLBACK_FUNC_DECL(DatabaseChangeVersion) if (!(args[0]->IsString() && args[1]->IsString())) return throwError("The old and new versions must be strings."); - Database* database = V8DOMWrapper::convertToNativeObject<Database>(V8ClassIndex::DATABASE, args.Holder()); + Database* database = V8Database::toNative(args.Holder()); Frame* frame = V8Proxy::retrieveFrameForCurrentContext(); if (!frame) @@ -95,7 +96,7 @@ static v8::Handle<v8::Value> createTransaction(const v8::Arguments& args, bool r if (!args[0]->IsObject()) return throwError("Transaction callback must be of valid type."); - Database* database = V8DOMWrapper::convertToNativeObject<Database>(V8ClassIndex::DATABASE, args.Holder()); + Database* database = V8Database::toNative(args.Holder()); Frame* frame = V8Proxy::retrieveFrameForCurrentContext(); if (!frame) @@ -123,13 +124,13 @@ static v8::Handle<v8::Value> createTransaction(const v8::Arguments& args, bool r return v8::Undefined(); } -CALLBACK_FUNC_DECL(DatabaseTransaction) +v8::Handle<v8::Value> V8Database::transactionCallback(const v8::Arguments& args) { INC_STATS("DOM.Database.transaction()"); return createTransaction(args, false); } -CALLBACK_FUNC_DECL(DatabaseReadTransaction) +v8::Handle<v8::Value> V8Database::readTransactionCallback(const v8::Arguments& args) { INC_STATS("DOM.Database.readTransaction()"); return createTransaction(args, true); diff --git a/WebCore/bindings/v8/custom/V8DedicatedWorkerContextCustom.cpp b/WebCore/bindings/v8/custom/V8DedicatedWorkerContextCustom.cpp index 263c005..4486dbe 100644 --- a/WebCore/bindings/v8/custom/V8DedicatedWorkerContextCustom.cpp +++ b/WebCore/bindings/v8/custom/V8DedicatedWorkerContextCustom.cpp @@ -31,10 +31,10 @@ #include "config.h" #if ENABLE(WORKERS) - -#include "WorkerContextExecutionProxy.h" +#include "V8DedicatedWorkerContext.h" #include "DedicatedWorkerContext.h" +#include "WorkerContextExecutionProxy.h" #include "V8Binding.h" #include "V8MessagePortCustom.h" #include "V8Proxy.h" @@ -42,11 +42,11 @@ namespace WebCore { -CALLBACK_FUNC_DECL(DedicatedWorkerContextPostMessage) +v8::Handle<v8::Value> V8DedicatedWorkerContext::postMessageCallback(const v8::Arguments& args) { INC_STATS(L"DOM.DedicatedWorkerContext.postMessage"); - DedicatedWorkerContext* workerContext = V8DOMWrapper::convertToNativeObject<DedicatedWorkerContext>(V8ClassIndex::DEDICATEDWORKERCONTEXT, args.Holder()); - RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(v8ValueToWebCoreString(args[0])); + DedicatedWorkerContext* workerContext = V8DedicatedWorkerContext::toNative(args.Holder()); + RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(args[0]); 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 ee68293..4aedde5 100644 --- a/WebCore/bindings/v8/custom/V8DocumentCustom.cpp +++ b/WebCore/bindings/v8/custom/V8DocumentCustom.cpp @@ -29,9 +29,10 @@ */ #include "config.h" -#include "Document.h" +#include "V8Document.h" #include "CanvasRenderingContext.h" +#include "Document.h" #include "ExceptionCode.h" #include "Node.h" #include "XPathNSResolver.h" @@ -53,16 +54,21 @@ namespace WebCore { -CALLBACK_FUNC_DECL(DocumentEvaluate) +v8::Handle<v8::Value> V8Document::evaluateCallback(const v8::Arguments& args) { INC_STATS("DOM.Document.evaluate()"); +<<<<<<< HEAD #if ENABLE(XPATH) RefPtr<Document> document = V8DOMWrapper::convertDOMWrapperToNode<Document>(args.Holder()); +======= + + RefPtr<Document> document = V8Document::toNative(args.Holder()); +>>>>>>> webkit.org at r54127 ExceptionCode ec = 0; String expression = toWebCoreString(args[0]); RefPtr<Node> contextNode; if (V8Node::HasInstance(args[1])) - contextNode = V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[1])); + contextNode = V8Node::toNative(v8::Handle<v8::Object>::Cast(args[1])); RefPtr<XPathNSResolver> resolver = V8DOMWrapper::getXPathNSResolver(args[2], V8Proxy::retrieve(V8Proxy::retrieveFrameForCallingContext())); if (!resolver && !args[2]->IsNull() && !args[2]->IsUndefined()) @@ -71,7 +77,7 @@ CALLBACK_FUNC_DECL(DocumentEvaluate) int type = toInt32(args[3]); RefPtr<XPathResult> inResult; if (V8XPathResult::HasInstance(args[4])) - inResult = V8DOMWrapper::convertToNativeObject<XPathResult>(V8ClassIndex::XPATHRESULT, v8::Handle<v8::Object>::Cast(args[4])); + inResult = V8XPathResult::toNative(v8::Handle<v8::Object>::Cast(args[4])); v8::TryCatch exceptionCatcher; RefPtr<XPathResult> result = document->evaluate(expression, contextNode.get(), resolver.get(), type, inResult.get(), ec); @@ -88,11 +94,11 @@ CALLBACK_FUNC_DECL(DocumentEvaluate) } -CALLBACK_FUNC_DECL(DocumentGetCSSCanvasContext) +v8::Handle<v8::Value> V8Document::getCSSCanvasContextCallback(const v8::Arguments& args) { INC_STATS("DOM.Document.getCSSCanvasContext"); v8::Handle<v8::Object> holder = args.Holder(); - Document* imp = V8DOMWrapper::convertDOMWrapperToNode<Document>(holder); + Document* imp = V8Document::toNative(holder); String contextId = toWebCoreString(args[0]); String name = toWebCoreString(args[1]); int width = toInt32(args[2]); @@ -110,4 +116,32 @@ CALLBACK_FUNC_DECL(DocumentGetCSSCanvasContext) return v8::Undefined(); } + +// DOMImplementation is a singleton in WebCore. If we use our normal +// mapping from DOM objects to V8 wrappers, the same wrapper will be +// shared for all frames in the same process. This is a major +// security problem. Therefore, we generate a DOMImplementation +// wrapper per document and store it in an internal field of the +// document. Since the DOMImplementation object is a singleton, we do +// not have to do anything to keep the DOMImplementation object alive +// for the lifetime of the wrapper. +v8::Handle<v8::Value> V8Document::implementationAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + ASSERT(info.Holder()->InternalFieldCount() >= internalFieldCount); + + // Check if the internal field already contains a wrapper. + v8::Local<v8::Value> implementation = info.Holder()->GetInternalField(V8Document::implementationIndex); + if (!implementation->IsUndefined()) + return implementation; + + // Generate a wrapper. + Document* document = V8Document::toNative(info.Holder()); + v8::Handle<v8::Value> wrapper = V8DOMWrapper::convertDOMImplementationToV8Object(document->implementation()); + + // Store the wrapper in the internal field. + info.Holder()->SetInternalField(implementationIndex, wrapper); + + return wrapper; +} + } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8DocumentLocationCustom.cpp b/WebCore/bindings/v8/custom/V8DocumentLocationCustom.cpp index 440bbdc..8dc4672 100644 --- a/WebCore/bindings/v8/custom/V8DocumentLocationCustom.cpp +++ b/WebCore/bindings/v8/custom/V8DocumentLocationCustom.cpp @@ -22,19 +22,20 @@ */ #include "config.h" -#include "V8CustomBinding.h" +#include "V8Document.h" #include "DOMWindow.h" #include "Frame.h" #include "V8Binding.h" +#include "V8CustomBinding.h" #include "V8Document.h" #include "V8Proxy.h" namespace WebCore { -ACCESSOR_GETTER(DocumentLocation) +v8::Handle<v8::Value> V8Document::locationAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { - Document* document = V8DOMWrapper::convertDOMWrapperToNative<Document>(info.Holder()); + Document* document = V8Document::toNative(info.Holder()); if (!document->frame()) return v8::Null(); @@ -42,15 +43,15 @@ ACCESSOR_GETTER(DocumentLocation) return V8DOMWrapper::convertToV8Object(V8ClassIndex::LOCATION, window->location()); } -ACCESSOR_SETTER(DocumentLocation) +void V8Document::locationAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { - Document* document = V8DOMWrapper::convertDOMWrapperToNative<Document>(info.Holder()); + Document* document = V8Document::toNative(info.Holder()); if (!document->frame()) return; DOMWindow* window = document->frame()->domWindow(); - // WindowSetLocation does security checks. // XXXMB- verify! - WindowSetLocation(window, toWebCoreString(value)); + // setLocation does security checks. // XXXMB- verify! + V8DOMWindowShell::setLocation(window, toWebCoreString(value)); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8ElementCustom.cpp b/WebCore/bindings/v8/custom/V8ElementCustom.cpp index e17e0a9..0f13f9d 100644 --- a/WebCore/bindings/v8/custom/V8ElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8ElementCustom.cpp @@ -29,11 +29,12 @@ */ #include "config.h" -#include "Element.h" +#include "V8Element.h" #include "Attr.h" #include "CSSHelper.h" #include "Document.h" +#include "Element.h" #include "ExceptionCode.h" #include "HTMLFrameElementBase.h" #include "HTMLNames.h" @@ -41,6 +42,7 @@ #include "V8Attr.h" #include "V8Binding.h" +#include "V8BindingState.h" #include "V8CustomBinding.h" #include "V8Proxy.h" @@ -48,14 +50,14 @@ namespace WebCore { -CALLBACK_FUNC_DECL(ElementSetAttribute) +v8::Handle<v8::Value> V8Element::setAttributeCallback(const v8::Arguments& args) { INC_STATS("DOM.Element.setAttribute()"); - Element* element = V8DOMWrapper::convertDOMWrapperToNode<Element>(args.Holder()); + Element* element = V8Element::toNative(args.Holder()); String name = toWebCoreString(args[0]); String value = toWebCoreString(args[1]); - if (!allowSettingSrcToJavascriptURL(element, name, value)) + if (!V8BindingSecurity::allowSettingSrcToJavascriptURL(V8BindingState::Only(), element, name, value)) return v8::Undefined(); ExceptionCode ec = 0; @@ -66,16 +68,16 @@ CALLBACK_FUNC_DECL(ElementSetAttribute) return v8::Undefined(); } -CALLBACK_FUNC_DECL(ElementSetAttributeNode) +v8::Handle<v8::Value> V8Element::setAttributeNodeCallback(const v8::Arguments& args) { INC_STATS("DOM.Element.setAttributeNode()"); if (!V8Attr::HasInstance(args[0])) return throwError(TYPE_MISMATCH_ERR); - Attr* newAttr = V8DOMWrapper::convertDOMWrapperToNode<Attr>(v8::Handle<v8::Object>::Cast(args[0])); - Element* element = V8DOMWrapper::convertDOMWrapperToNode<Element>(args.Holder()); + Attr* newAttr = V8Attr::toNative(v8::Handle<v8::Object>::Cast(args[0])); + Element* element = V8Element::toNative(args.Holder()); - if (!allowSettingSrcToJavascriptURL(element, newAttr->name(), newAttr->value())) + if (!V8BindingSecurity::allowSettingSrcToJavascriptURL(V8BindingState::Only(), element, newAttr->name(), newAttr->value())) return v8::Undefined(); ExceptionCode ec = 0; @@ -86,15 +88,15 @@ CALLBACK_FUNC_DECL(ElementSetAttributeNode) return V8DOMWrapper::convertNodeToV8Object(result.release()); } -CALLBACK_FUNC_DECL(ElementSetAttributeNS) +v8::Handle<v8::Value> V8Element::setAttributeNSCallback(const v8::Arguments& args) { INC_STATS("DOM.Element.setAttributeNS()"); - Element* element = V8DOMWrapper::convertDOMWrapperToNode<Element>(args.Holder()); + Element* element = V8Element::toNative(args.Holder()); String namespaceURI = toWebCoreStringWithNullCheck(args[0]); String qualifiedName = toWebCoreString(args[1]); String value = toWebCoreString(args[2]); - if (!allowSettingSrcToJavascriptURL(element, qualifiedName, value)) + if (!V8BindingSecurity::allowSettingSrcToJavascriptURL(V8BindingState::Only(), element, qualifiedName, value)) return v8::Undefined(); ExceptionCode ec = 0; @@ -105,16 +107,16 @@ CALLBACK_FUNC_DECL(ElementSetAttributeNS) return v8::Undefined(); } -CALLBACK_FUNC_DECL(ElementSetAttributeNodeNS) +v8::Handle<v8::Value> V8Element::setAttributeNodeNSCallback(const v8::Arguments& args) { INC_STATS("DOM.Element.setAttributeNodeNS()"); if (!V8Attr::HasInstance(args[0])) return throwError(TYPE_MISMATCH_ERR); - Attr* newAttr = V8DOMWrapper::convertDOMWrapperToNode<Attr>(v8::Handle<v8::Object>::Cast(args[0])); - Element* element = V8DOMWrapper::convertDOMWrapperToNode<Element>(args.Holder()); + Attr* newAttr = V8Attr::toNative(v8::Handle<v8::Object>::Cast(args[0])); + Element* element = V8Element::toNative(args.Holder()); - if (!allowSettingSrcToJavascriptURL(element, newAttr->name(), newAttr->value())) + if (!V8BindingSecurity::allowSettingSrcToJavascriptURL(V8BindingState::Only(), element, newAttr->name(), newAttr->value())) return v8::Undefined(); ExceptionCode ec = 0; diff --git a/WebCore/bindings/v8/custom/V8EventCustom.cpp b/WebCore/bindings/v8/custom/V8EventCustom.cpp index 8bac40f..65cd41e 100644 --- a/WebCore/bindings/v8/custom/V8EventCustom.cpp +++ b/WebCore/bindings/v8/custom/V8EventCustom.cpp @@ -29,27 +29,27 @@ */ #include "config.h" -#include "Event.h" +#include "V8Event.h" #include "Clipboard.h" #include "ClipboardEvent.h" +#include "Event.h" #include "MouseEvent.h" - #include "V8Binding.h" #include "V8CustomBinding.h" #include "V8Proxy.h" namespace WebCore { -ACCESSOR_SETTER(EventReturnValue) +void V8Event::valueAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { - Event* event = V8DOMWrapper::convertDOMWrapperToNative<Event>(info.Holder()); + Event* event = V8Event::toNative(info.Holder()); event->setDefaultPrevented(!value->BooleanValue()); } -ACCESSOR_GETTER(EventDataTransfer) +v8::Handle<v8::Value> V8Event::dataTransferAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { - Event* event = V8DOMWrapper::convertDOMWrapperToNative<Event>(info.Holder()); + Event* event = V8Event::toNative(info.Holder()); if (event->isDragEvent()) return V8DOMWrapper::convertToV8Object(V8ClassIndex::CLIPBOARD, static_cast<MouseEvent*>(event)->clipboard()); @@ -57,9 +57,9 @@ ACCESSOR_GETTER(EventDataTransfer) return v8::Undefined(); } -ACCESSOR_GETTER(EventClipboardData) +v8::Handle<v8::Value> V8Event::clipboardDataAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { - Event* event = V8DOMWrapper::convertDOMWrapperToNative<Event>(info.Holder()); + Event* event = V8Event::toNative(info.Holder()); if (event->isClipboardEvent()) return V8DOMWrapper::convertToV8Object(V8ClassIndex::CLIPBOARD, static_cast<ClipboardEvent*>(event)->clipboard()); @@ -67,16 +67,4 @@ ACCESSOR_GETTER(EventClipboardData) return v8::Undefined(); } -ACCESSOR_GETTER(EventSrcElement) -{ - Event* event = V8DOMWrapper::convertDOMWrapperToNative<Event>(info.Holder()); - return V8DOMWrapper::convertEventTargetToV8Object(event->target()); -} - -ACCESSOR_GETTER(EventReturnValue) -{ - Event* event = V8DOMWrapper::convertDOMWrapperToNative<Event>(info.Holder()); - return event->defaultPrevented() ? v8::False() : v8::True(); -} - } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8HTMLSelectElementCollectionCustom.cpp b/WebCore/bindings/v8/custom/V8EventSourceConstructor.cpp index 0dfa515..458c35d 100644 --- a/WebCore/bindings/v8/custom/V8HTMLSelectElementCollectionCustom.cpp +++ b/WebCore/bindings/v8/custom/V8EventSourceConstructor.cpp @@ -1,5 +1,5 @@ /* - * 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 @@ -29,50 +29,52 @@ */ #include "config.h" -#include "HTMLSelectElement.h" -#include "HTMLOptionsCollection.h" +#if ENABLE(EVENTSOURCE) +#include "V8EventSource.h" + +#include "EventSource.h" +#include "Frame.h" #include "V8Binding.h" -#include "V8Collection.h" #include "V8CustomBinding.h" -#include "V8NamedNodesCollection.h" #include "V8Proxy.h" +#include "V8Utilities.h" +#include "WorkerContext.h" +#include "WorkerContextExecutionProxy.h" namespace WebCore { -NAMED_PROPERTY_GETTER(HTMLSelectElementCollection) +v8::Handle<v8::Value> V8EventSource::constructorCallback(const v8::Arguments& args) { - INC_STATS("DOM.HTMLSelectElementCollection.NamedPropertySetter"); - HTMLSelectElement* select = V8DOMWrapper::convertDOMWrapperToNode<HTMLSelectElement>(info.Holder()); - v8::Handle<v8::Value> value = info.Holder()->GetRealNamedPropertyInPrototypeChain(name); - - if (!value.IsEmpty()) - return value; - - // Search local callback properties next to find IDL defined properties. - if (info.Holder()->HasRealNamedCallbackProperty(name)) - return notHandledByInterceptor(); + INC_STATS("DOM.EventSource.Constructor"); - PassRefPtr<HTMLOptionsCollection> collection = select->options(); + if (!args.IsConstructCall()) + return throwError("DOM object constructor cannot be called as a function.", V8Proxy::TypeError); - Vector<RefPtr<Node> > items; - collection->namedItems(v8StringToAtomicWebCoreString(name), items); + // Expect one parameter. + // Allocate an EventSource object as its internal field. + ScriptExecutionContext* context = getScriptExecutionContext(); + 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); - if (!items.size()) - return notHandledByInterceptor(); + ExceptionCode ec = 0; + String url = toWebCoreString(args[0]); - if (items.size() == 1) - return V8DOMWrapper::convertNodeToV8Object(items.at(0).release()); + RefPtr<EventSource> eventSource = EventSource::create(url, context, ec); + + if (ec) + return throwError(ec); - NodeList* list = new V8NamedNodesCollection(items); - return V8DOMWrapper::convertToV8Object(V8ClassIndex::NODELIST, list); -} + V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::EVENTSOURCE), eventSource.get()); -INDEXED_PROPERTY_SETTER(HTMLSelectElementCollection) -{ - INC_STATS("DOM.HTMLSelectElementCollection.IndexedPropertySetter"); - HTMLSelectElement* select = V8DOMWrapper::convertDOMWrapperToNode<HTMLSelectElement>(info.Holder()); - return toOptionsCollectionSetter(index, value, select); + // Add object to the wrapper map. + eventSource->ref(); + V8DOMWrapper::setJSWrapperForActiveDOMObject(eventSource.get(), v8::Persistent<v8::Object>::New(args.Holder())); + return args.Holder(); } } // namespace WebCore + +#endif // ENABLE(EVENTSOURCE) diff --git a/WebCore/bindings/v8/custom/V8EventSourceCustom.cpp b/WebCore/bindings/v8/custom/V8EventSourceCustom.cpp new file mode 100644 index 0000000..e603549 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8EventSourceCustom.cpp @@ -0,0 +1,74 @@ +/* + * 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 "V8CustomBinding.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/V8GeolocationCustom.cpp b/WebCore/bindings/v8/custom/V8GeolocationCustom.cpp index 011beff..6bd9ff2 100644 --- a/WebCore/bindings/v8/custom/V8GeolocationCustom.cpp +++ b/WebCore/bindings/v8/custom/V8GeolocationCustom.cpp @@ -24,6 +24,8 @@ */ #include "config.h" +#include "V8Geolocation.h" + #include "Geolocation.h" #include "V8Binding.h" @@ -165,7 +167,7 @@ static PassRefPtr<PositionOptions> createPositionOptions(v8::Local<v8::Value> va return options.release(); } -CALLBACK_FUNC_DECL(GeolocationGetCurrentPosition) +v8::Handle<v8::Value> V8Geolocation::getCurrentPositionCallback(const v8::Arguments& args) { INC_STATS("DOM.Geolocation.getCurrentPosition()"); @@ -185,12 +187,12 @@ CALLBACK_FUNC_DECL(GeolocationGetCurrentPosition) return v8::Undefined(); ASSERT(positionOptions); - Geolocation* geolocation = V8DOMWrapper::convertToNativeObject<Geolocation>(V8ClassIndex::GEOLOCATION, args.Holder()); + Geolocation* geolocation = V8Geolocation::toNative(args.Holder()); geolocation->getCurrentPosition(positionCallback.release(), positionErrorCallback.release(), positionOptions.release()); return v8::Undefined(); } -CALLBACK_FUNC_DECL(GeolocationWatchPosition) +v8::Handle<v8::Value> V8Geolocation::watchPositionCallback(const v8::Arguments& args) { INC_STATS("DOM.Geolocation.watchPosition()"); @@ -210,7 +212,7 @@ CALLBACK_FUNC_DECL(GeolocationWatchPosition) return v8::Undefined(); ASSERT(positionOptions); - Geolocation* geolocation = V8DOMWrapper::convertToNativeObject<Geolocation>(V8ClassIndex::GEOLOCATION, args.Holder()); + Geolocation* geolocation = V8Geolocation::toNative(args.Holder()); int watchId = geolocation->watchPosition(positionCallback.release(), positionErrorCallback.release(), positionOptions.release()); return v8::Number::New(watchId); } diff --git a/WebCore/bindings/v8/custom/V8HTMLAllCollectionCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLAllCollectionCustom.cpp index 419f374..c34d9e7 100644 --- a/WebCore/bindings/v8/custom/V8HTMLAllCollectionCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLAllCollectionCustom.cpp @@ -29,6 +29,8 @@ */ #include "config.h" +#include "V8HTMLAllCollection.h" + #include "HTMLAllCollection.h" #include "V8Binding.h" @@ -69,7 +71,7 @@ static v8::Handle<v8::Value> getItem(HTMLAllCollection* collection, v8::Handle<v return V8DOMWrapper::convertNodeToV8Object(result.release()); } -NAMED_PROPERTY_GETTER(HTMLAllCollection) +v8::Handle<v8::Value> V8HTMLAllCollection::namedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.HTMLAllCollection.NamedPropertyGetter"); // Search the prototype chain first. @@ -84,21 +86,21 @@ NAMED_PROPERTY_GETTER(HTMLAllCollection) return v8::Handle<v8::Value>(); // Finally, search the DOM structure. - HTMLAllCollection* imp = V8DOMWrapper::convertToNativeObject<HTMLAllCollection>(V8ClassIndex::HTMLALLCOLLECTION, info.Holder()); + HTMLAllCollection* imp = V8HTMLAllCollection::toNative(info.Holder()); return getNamedItems(imp, v8StringToAtomicWebCoreString(name)); } -CALLBACK_FUNC_DECL(HTMLAllCollectionItem) +v8::Handle<v8::Value> V8HTMLAllCollection::itemCallback(const v8::Arguments& args) { INC_STATS("DOM.HTMLAllCollection.item()"); - HTMLAllCollection* imp = V8DOMWrapper::convertToNativeObject<HTMLAllCollection>(V8ClassIndex::HTMLALLCOLLECTION, args.Holder()); + HTMLAllCollection* imp = V8HTMLAllCollection::toNative(args.Holder()); return getItem(imp, args[0]); } -CALLBACK_FUNC_DECL(HTMLAllCollectionNamedItem) +v8::Handle<v8::Value> V8HTMLAllCollection::namedItemCallback(const v8::Arguments& args) { INC_STATS("DOM.HTMLAllCollection.namedItem()"); - HTMLAllCollection* imp = V8DOMWrapper::convertToNativeObject<HTMLAllCollection>(V8ClassIndex::HTMLALLCOLLECTION, args.Holder()); + HTMLAllCollection* imp = V8HTMLAllCollection::toNative(args.Holder()); v8::Handle<v8::Value> result = getNamedItems(imp, toWebCoreString(args[0])); if (result.IsEmpty()) @@ -107,13 +109,13 @@ CALLBACK_FUNC_DECL(HTMLAllCollectionNamedItem) return result; } -CALLBACK_FUNC_DECL(HTMLAllCollectionCallAsFunction) +v8::Handle<v8::Value> V8HTMLAllCollection::callAsFunctionCallback(const v8::Arguments& args) { INC_STATS("DOM.HTMLAllCollection.callAsFunction()"); if (args.Length() < 1) return v8::Undefined(); - HTMLAllCollection* imp = V8DOMWrapper::convertToNativeObject<HTMLAllCollection>(V8ClassIndex::HTMLALLCOLLECTION, args.Holder()); + HTMLAllCollection* imp = V8HTMLAllCollection::toNative(args.Holder()); if (args.Length() == 1) return getItem(imp, args[0]); diff --git a/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.cpp b/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.cpp index c82d88a..e634003 100644 --- a/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.cpp @@ -35,8 +35,8 @@ #include "Document.h" #include "Frame.h" #include "HTMLNames.h" - #include "V8Binding.h" +#include "V8HTMLAudioElement.h" #include "V8Proxy.h" #include <wtf/RefPtr.h> @@ -53,7 +53,7 @@ v8::Persistent<v8::FunctionTemplate> V8HTMLAudioElementConstructor::GetTemplate( v8::Local<v8::FunctionTemplate> result = v8::FunctionTemplate::New(USE_CALLBACK(HTMLAudioElementConstructor)); v8::Local<v8::ObjectTemplate> instance = result->InstanceTemplate(); - instance->SetInternalFieldCount(V8Custom::kNodeMinimumInternalFieldCount); + instance->SetInternalFieldCount(V8HTMLAudioElement::internalFieldCount); result->SetClassName(v8::String::New("HTMLAudioElement")); result->Inherit(V8DOMWrapper::getTemplate(V8ClassIndex::HTMLAUDIOELEMENT)); @@ -61,7 +61,7 @@ v8::Persistent<v8::FunctionTemplate> V8HTMLAudioElementConstructor::GetTemplate( return cachedTemplate; } -CALLBACK_FUNC_DECL(HTMLAudioElementConstructor) +v8::Handle<v8::Value> V8Custom::v8HTMLAudioElementConstructorCallback(const v8::Arguments& args) { INC_STATS("DOM.HTMLAudioElement.Contructor"); diff --git a/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp index e51437e..0d1ff44 100644 --- a/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp @@ -29,10 +29,12 @@ */ #include "config.h" -#include "HTMLCanvasElement.h" -#include "CanvasRenderingContext.h" +#include "V8HTMLCanvasElement.h" +#include "CanvasContextAttributes.h" #include "CanvasRenderingContext.h" +#include "HTMLCanvasElement.h" +#include "WebGLContextAttributes.h" #include "V8Binding.h" #include "V8CustomBinding.h" #include "V8Node.h" @@ -40,13 +42,38 @@ namespace WebCore { -CALLBACK_FUNC_DECL(HTMLCanvasElementGetContext) +v8::Handle<v8::Value> V8HTMLCanvasElement::getContextCallback(const v8::Arguments& args) { INC_STATS("DOM.HTMLCanvasElement.context"); v8::Handle<v8::Object> holder = args.Holder(); - HTMLCanvasElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLCanvasElement>(holder); + HTMLCanvasElement* imp = V8HTMLCanvasElement::toNative(holder); String contextId = toWebCoreString(args[0]); - CanvasRenderingContext* result = imp->getContext(contextId); + RefPtr<CanvasContextAttributes> attrs; +#if ENABLE(3D_CANVAS) + if (contextId == "experimental-webgl" || contextId == "webkit-3d") { + attrs = WebGLContextAttributes::create(); + WebGLContextAttributes* webGLAttrs = static_cast<WebGLContextAttributes*>(attrs.get()); + if (args.Length() > 1 && args[0]->IsObject()) { + v8::Handle<v8::Object> jsAttrs = args[1]->ToObject(); + v8::Handle<v8::String> alpha = v8::String::New("alpha"); + if (jsAttrs->Has(alpha)) + webGLAttrs->setAlpha(jsAttrs->Get(alpha)->BooleanValue()); + v8::Handle<v8::String> depth = v8::String::New("depth"); + if (jsAttrs->Has(depth)) + webGLAttrs->setDepth(jsAttrs->Get(depth)->BooleanValue()); + v8::Handle<v8::String> stencil = v8::String::New("stencil"); + if (jsAttrs->Has(stencil)) + webGLAttrs->setStencil(jsAttrs->Get(stencil)->BooleanValue()); + v8::Handle<v8::String> antialias = v8::String::New("antialias"); + if (jsAttrs->Has(antialias)) + webGLAttrs->setAntialias(jsAttrs->Get(antialias)->BooleanValue()); + v8::Handle<v8::String> premultipliedAlpha = v8::String::New("premultipliedAlpha"); + if (jsAttrs->Has(premultipliedAlpha)) + webGLAttrs->setPremultipliedAlpha(jsAttrs->Get(premultipliedAlpha)->BooleanValue()); + } + } +#endif + CanvasRenderingContext* result = imp->getContext(contextId, attrs.get()); if (!result) return v8::Undefined(); if (result->is2d()) @@ -60,4 +87,3 @@ CALLBACK_FUNC_DECL(HTMLCanvasElementGetContext) } } // namespace WebCore - diff --git a/WebCore/bindings/v8/custom/V8HTMLCollectionCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLCollectionCustom.cpp index 7c9b40f..8bb3c3a 100644 --- a/WebCore/bindings/v8/custom/V8HTMLCollectionCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLCollectionCustom.cpp @@ -29,8 +29,9 @@ */ #include "config.h" -#include "HTMLCollection.h" +#include "V8HTMLCollection.h" +#include "HTMLCollection.h" #include "V8Binding.h" #include "V8CustomBinding.h" #include "V8NamedNodesCollection.h" @@ -69,7 +70,7 @@ static v8::Handle<v8::Value> getItem(HTMLCollection* collection, v8::Handle<v8:: return V8DOMWrapper::convertNodeToV8Object(result.release()); } -NAMED_PROPERTY_GETTER(HTMLCollection) +v8::Handle<v8::Value> V8HTMLCollection::namedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.HTMLCollection.NamedPropertyGetter"); // Search the prototype chain first. @@ -84,21 +85,21 @@ NAMED_PROPERTY_GETTER(HTMLCollection) return v8::Handle<v8::Value>(); // Finally, search the DOM structure. - HTMLCollection* imp = V8DOMWrapper::convertToNativeObject<HTMLCollection>(V8ClassIndex::HTMLCOLLECTION, info.Holder()); + HTMLCollection* imp = V8HTMLCollection::toNative(info.Holder()); return getNamedItems(imp, v8StringToAtomicWebCoreString(name)); } -CALLBACK_FUNC_DECL(HTMLCollectionItem) +v8::Handle<v8::Value> V8HTMLCollection::itemCallback(const v8::Arguments& args) { INC_STATS("DOM.HTMLCollection.item()"); - HTMLCollection* imp = V8DOMWrapper::convertToNativeObject<HTMLCollection>(V8ClassIndex::HTMLCOLLECTION, args.Holder()); + HTMLCollection* imp = V8HTMLCollection::toNative(args.Holder()); return getItem(imp, args[0]); } -CALLBACK_FUNC_DECL(HTMLCollectionNamedItem) +v8::Handle<v8::Value> V8HTMLCollection::namedItemCallback(const v8::Arguments& args) { INC_STATS("DOM.HTMLCollection.namedItem()"); - HTMLCollection* imp = V8DOMWrapper::convertToNativeObject<HTMLCollection>(V8ClassIndex::HTMLCOLLECTION, args.Holder()); + HTMLCollection* imp = V8HTMLCollection::toNative(args.Holder()); v8::Handle<v8::Value> result = getNamedItems(imp, toWebCoreString(args[0])); if (result.IsEmpty()) @@ -107,13 +108,13 @@ CALLBACK_FUNC_DECL(HTMLCollectionNamedItem) return result; } -CALLBACK_FUNC_DECL(HTMLCollectionCallAsFunction) +v8::Handle<v8::Value> V8HTMLCollection::callAsFunctionCallback(const v8::Arguments& args) { INC_STATS("DOM.HTMLCollection.callAsFunction()"); if (args.Length() < 1) return v8::Undefined(); - HTMLCollection* imp = V8DOMWrapper::convertToNativeObject<HTMLCollection>(V8ClassIndex::HTMLCOLLECTION, args.Holder()); + HTMLCollection* imp = V8HTMLCollection::toNative(args.Holder()); if (args.Length() == 1) return getItem(imp, args[0]); diff --git a/WebCore/bindings/v8/custom/V8HTMLDocumentCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLDocumentCustom.cpp index 9cf2f3d..13243ef 100644 --- a/WebCore/bindings/v8/custom/V8HTMLDocumentCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLDocumentCustom.cpp @@ -29,24 +29,22 @@ */ #include "config.h" -#include "HTMLDocument.h" +#include "V8HTMLDocument.h" #include "Frame.h" #include "HTMLAllCollection.h" +#include "HTMLDocument.h" #include "HTMLCollection.h" #include "HTMLIFrameElement.h" #include "HTMLNames.h" - #include "V8Binding.h" -#include "V8CustomBinding.h" #include "V8Proxy.h" - #include <wtf/RefPtr.h> #include <wtf/StdLibExtras.h> namespace WebCore { -NAMED_PROPERTY_DELETER(HTMLDocument) +v8::Handle<v8::Boolean> V8HTMLDocument::namedPropertyDeleter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { // Only handle document.all. Insert the marker object into the // shadow internal field to signal that document.all is no longer @@ -56,13 +54,13 @@ NAMED_PROPERTY_DELETER(HTMLDocument) if (key != all) return deletionNotHandledByInterceptor(); - ASSERT(info.Holder()->InternalFieldCount() == kHTMLDocumentInternalFieldCount); - v8::Local<v8::Value> marker = info.Holder()->GetInternalField(kHTMLDocumentMarkerIndex); - info.Holder()->SetInternalField(kHTMLDocumentShadowIndex, marker); + ASSERT(info.Holder()->InternalFieldCount() == V8HTMLDocument::internalFieldCount); + v8::Local<v8::Value> marker = info.Holder()->GetInternalField(V8HTMLDocument::markerIndex); + info.Holder()->SetInternalField(V8HTMLDocument::shadowIndex, marker); return v8::True(); } -NAMED_PROPERTY_GETTER(HTMLDocument) +v8::Handle<v8::Value> V8HTMLDocument::namedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.HTMLDocument.NamedPropertyGetter"); AtomicString key = v8StringToAtomicWebCoreString(name); @@ -72,14 +70,14 @@ NAMED_PROPERTY_GETTER(HTMLDocument) // been temporarily shadowed and we return the value. DEFINE_STATIC_LOCAL(const AtomicString, all, ("all")); if (key == all) { - ASSERT(info.Holder()->InternalFieldCount() == kHTMLDocumentInternalFieldCount); - v8::Local<v8::Value> marker = info.Holder()->GetInternalField(kHTMLDocumentMarkerIndex); - v8::Local<v8::Value> value = info.Holder()->GetInternalField(kHTMLDocumentShadowIndex); + ASSERT(info.Holder()->InternalFieldCount() == V8HTMLDocument::internalFieldCount); + v8::Local<v8::Value> marker = info.Holder()->GetInternalField(V8HTMLDocument::markerIndex); + v8::Local<v8::Value> value = info.Holder()->GetInternalField(V8HTMLDocument::shadowIndex); if (marker != value) return value; } - HTMLDocument* htmlDocument = V8DOMWrapper::convertDOMWrapperToNode<HTMLDocument>(info.Holder()); + HTMLDocument* htmlDocument = V8HTMLDocument::toNative(info.Holder()); // Fast case for named elements that are not there. if (!htmlDocument->hasNamedItem(key.impl()) && !htmlDocument->hasExtraNamedItem(key.impl())) @@ -101,6 +99,13 @@ NAMED_PROPERTY_GETTER(HTMLDocument) return V8DOMWrapper::convertToV8Object(V8ClassIndex::HTMLCOLLECTION, items.release()); } +v8::Handle<v8::Value> V8HTMLDocument::indexedPropertyGetter(uint32_t index, const v8::AccessorInfo &info) +{ + INC_STATS("DOM.HTMLDocument.IndexedPropertyGetter"); + v8::Local<v8::Integer> indexV8 = v8::Integer::NewFromUnsigned(index); + return namedPropertyGetter(indexV8->ToString(), info); +} + // HTMLDocument ---------------------------------------------------------------- // Concatenates "args" to a string. If args is empty, returns empty string. @@ -115,28 +120,28 @@ static String writeHelperGetString(const v8::Arguments& args) return str; } -CALLBACK_FUNC_DECL(HTMLDocumentWrite) +v8::Handle<v8::Value> V8HTMLDocument::writeCallback(const v8::Arguments& args) { INC_STATS("DOM.HTMLDocument.write()"); - HTMLDocument* htmlDocument = V8DOMWrapper::convertDOMWrapperToNode<HTMLDocument>(args.Holder()); + HTMLDocument* htmlDocument = V8HTMLDocument::toNative(args.Holder()); Frame* frame = V8Proxy::retrieveFrameForCallingContext(); htmlDocument->write(writeHelperGetString(args), frame ? frame->document() : NULL); return v8::Undefined(); } -CALLBACK_FUNC_DECL(HTMLDocumentWriteln) +v8::Handle<v8::Value> V8HTMLDocument::writelnCallback(const v8::Arguments& args) { INC_STATS("DOM.HTMLDocument.writeln()"); - HTMLDocument* htmlDocument = V8DOMWrapper::convertDOMWrapperToNode<HTMLDocument>(args.Holder()); + HTMLDocument* htmlDocument = V8HTMLDocument::toNative(args.Holder()); Frame* frame = V8Proxy::retrieveFrameForCallingContext(); htmlDocument->writeln(writeHelperGetString(args), frame ? frame->document() : NULL); return v8::Undefined(); } -CALLBACK_FUNC_DECL(HTMLDocumentOpen) +v8::Handle<v8::Value> V8HTMLDocument::openCallback(const v8::Arguments& args) { INC_STATS("DOM.HTMLDocument.open()"); - HTMLDocument* htmlDocument = V8DOMWrapper::convertDOMWrapperToNode<HTMLDocument>(args.Holder()); + HTMLDocument* htmlDocument = V8HTMLDocument::toNative(args.Holder()); if (args.Length() > 2) { if (Frame* frame = htmlDocument->frame()) { @@ -173,21 +178,21 @@ CALLBACK_FUNC_DECL(HTMLDocumentOpen) return args.Holder(); } -ACCESSOR_GETTER(HTMLDocumentAll) +v8::Handle<v8::Value> V8HTMLDocument::allAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.HTMLDocument.all._get"); v8::HandleScope scope; v8::Handle<v8::Object> holder = info.Holder(); - HTMLDocument* htmlDocument = V8DOMWrapper::convertDOMWrapperToNode<HTMLDocument>(holder); + HTMLDocument* htmlDocument = V8HTMLDocument::toNative(holder); return V8DOMWrapper::convertToV8Object(V8ClassIndex::HTMLCOLLECTION, htmlDocument->all()); } -ACCESSOR_SETTER(HTMLDocumentAll) +void V8HTMLDocument::allAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { INC_STATS("DOM.HTMLDocument.all._set"); v8::Handle<v8::Object> holder = info.Holder(); - ASSERT(info.Holder()->InternalFieldCount() == kHTMLDocumentInternalFieldCount); - info.Holder()->SetInternalField(kHTMLDocumentShadowIndex, value); + ASSERT(info.Holder()->InternalFieldCount() == V8HTMLDocument::internalFieldCount); + info.Holder()->SetInternalField(V8HTMLDocument::shadowIndex, value); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8HTMLFormElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLFormElementCustom.cpp index 1ec09f7..d819e9b 100644 --- a/WebCore/bindings/v8/custom/V8HTMLFormElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLFormElementCustom.cpp @@ -29,9 +29,10 @@ */ #include "config.h" -#include "HTMLFormElement.h" +#include "V8HTMLFormElement.h" #include "HTMLCollection.h" +#include "HTMLFormElement.h" #include "V8Binding.h" #include "V8CustomBinding.h" #include "V8NamedNodesCollection.h" @@ -39,10 +40,10 @@ namespace WebCore { -INDEXED_PROPERTY_GETTER(HTMLFormElement) +v8::Handle<v8::Value> V8HTMLFormElement::indexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info) { INC_STATS("DOM.HTMLFormElement.IndexedPropertyGetter"); - HTMLFormElement* form = V8DOMWrapper::convertDOMWrapperToNode<HTMLFormElement>(info.Holder()); + HTMLFormElement* form = V8HTMLFormElement::toNative(info.Holder()); RefPtr<Node> formElement = form->elements()->item(index); if (!formElement) @@ -50,11 +51,10 @@ INDEXED_PROPERTY_GETTER(HTMLFormElement) return V8DOMWrapper::convertNodeToV8Object(formElement.release()); } - -NAMED_PROPERTY_GETTER(HTMLFormElement) +v8::Handle<v8::Value> V8HTMLFormElement::namedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.HTMLFormElement.NamedPropertyGetter"); - HTMLFormElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLFormElement>(info.Holder()); + HTMLFormElement* imp = V8HTMLFormElement::toNative(info.Holder()); AtomicString v = v8StringToAtomicWebCoreString(name); // Call getNamedElements twice, first time check if it has a value @@ -80,10 +80,15 @@ NAMED_PROPERTY_GETTER(HTMLFormElement) return V8DOMWrapper::convertToV8Object(V8ClassIndex::NODELIST, collection); } -CALLBACK_FUNC_DECL(HTMLFormElementSubmit) { +v8::Handle<v8::Value> V8HTMLFormElement::submitCallback(const v8::Arguments& args) +{ INC_STATS("DOM.HTMLFormElement.submit()"); - HTMLFormElement* form = V8DOMWrapper::convertDOMWrapperToNative<HTMLFormElement>(args.Holder()); - form->submit(0, false, false); + HTMLFormElement* form = V8HTMLFormElement::toNative(args.Holder()); + Frame* frame = V8Proxy::retrieveFrameForEnteredContext(); + if (!frame) + return v8::Undefined(); + + form->submit(frame); return v8::Undefined(); } diff --git a/WebCore/bindings/v8/custom/V8HTMLFrameElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLFrameElementCustom.cpp index 2f55758..fd831bf 100644 --- a/WebCore/bindings/v8/custom/V8HTMLFrameElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLFrameElementCustom.cpp @@ -29,10 +29,12 @@ */ #include "config.h" +#include "V8HTMLFrameElement.h" + #include "HTMLFrameElement.h" #include "HTMLNames.h" - #include "V8Binding.h" +#include "V8BindingState.h" #include "V8CustomBinding.h" #include "V8Proxy.h" @@ -40,23 +42,23 @@ namespace WebCore { using namespace HTMLNames; -ACCESSOR_SETTER(HTMLFrameElementSrc) +void V8HTMLFrameElement::srcAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { - HTMLFrameElement* frame = V8DOMWrapper::convertDOMWrapperToNode<HTMLFrameElement>(info.Holder()); + HTMLFrameElement* frame = V8HTMLFrameElement::toNative(info.Holder()); String srcValue = toWebCoreStringWithNullCheck(value); - if (!allowSettingFrameSrcToJavascriptUrl(frame, srcValue)) + if (!V8BindingSecurity::allowSettingFrameSrcToJavascriptUrl(V8BindingState::Only(), frame, srcValue)) return; frame->setAttribute(srcAttr, srcValue); } -ACCESSOR_SETTER(HTMLFrameElementLocation) +void V8HTMLFrameElement::locationAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { - HTMLFrameElement* frame = V8DOMWrapper::convertDOMWrapperToNode<HTMLFrameElement>(info.Holder()); + HTMLFrameElement* frame = V8HTMLFrameElement::toNative(info.Holder()); String locationValue = toWebCoreStringWithNullCheck(value); - if (!allowSettingFrameSrcToJavascriptUrl(frame, locationValue)) + if (!V8BindingSecurity::allowSettingFrameSrcToJavascriptUrl(V8BindingState::Only(), frame, locationValue)) return; frame->setLocation(locationValue); diff --git a/WebCore/bindings/v8/custom/V8HTMLFrameSetElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLFrameSetElementCustom.cpp index e8e2e72..214b11e 100644 --- a/WebCore/bindings/v8/custom/V8HTMLFrameSetElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLFrameSetElementCustom.cpp @@ -29,12 +29,13 @@ */ #include "config.h" -#include "HTMLFrameSetElement.h" +#include "V8HTMLFrameSetElement.h" #include "Document.h" #include "Frame.h" #include "HTMLCollection.h" #include "HTMLFrameElement.h" +#include "HTMLFrameSetElement.h" #include "HTMLNames.h" #include "Node.h" @@ -44,10 +45,10 @@ namespace WebCore { -NAMED_PROPERTY_GETTER(HTMLFrameSetElement) +v8::Handle<v8::Value> V8HTMLFrameSetElement::namedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.HTMLFrameSetElement.NamedPropertyGetter"); - HTMLFrameSetElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLFrameSetElement>(info.Holder()); + HTMLFrameSetElement* imp = V8HTMLFrameSetElement::toNative(info.Holder()); Node* frameNode = imp->children()->namedItem(v8StringToAtomicWebCoreString(name)); if (frameNode && frameNode->hasTagName(HTMLNames::frameTag)) { Document* doc = static_cast<HTMLFrameElement*>(frameNode)->contentDocument(); diff --git a/WebCore/bindings/v8/custom/V8HTMLIFrameElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLIFrameElementCustom.cpp index a4863e8..1949632 100644 --- a/WebCore/bindings/v8/custom/V8HTMLIFrameElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLIFrameElementCustom.cpp @@ -29,10 +29,12 @@ */ #include "config.h" +#include "V8HTMLIFrameElement.h" + #include "HTMLIFrameElement.h" #include "HTMLNames.h" - #include "V8Binding.h" +#include "V8BindingState.h" #include "V8CustomBinding.h" #include "V8Proxy.h" @@ -40,12 +42,12 @@ namespace WebCore { using namespace HTMLNames; -ACCESSOR_SETTER(HTMLIFrameElementSrc) +void V8HTMLIFrameElement::srcAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { - HTMLIFrameElement* iframe = V8DOMWrapper::convertDOMWrapperToNode<HTMLIFrameElement>(info.Holder()); + HTMLIFrameElement* iframe = V8HTMLIFrameElement::toNative(info.Holder()); String v = toWebCoreStringWithNullCheck(value); - if (!allowSettingFrameSrcToJavascriptUrl(iframe, v)) + if (!V8BindingSecurity::allowSettingFrameSrcToJavascriptUrl(V8BindingState::Only(), iframe, v)) return; iframe->setAttribute(srcAttr, v); diff --git a/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp b/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp index 71c99cf..57efa34 100644 --- a/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp @@ -35,8 +35,8 @@ #include "Document.h" #include "Frame.h" #include "HTMLNames.h" - #include "V8Binding.h" +#include "V8HTMLImageElement.h" #include "V8Proxy.h" #include <wtf/RefPtr.h> @@ -53,7 +53,7 @@ v8::Persistent<v8::FunctionTemplate> V8HTMLImageElementConstructor::GetTemplate( v8::Local<v8::FunctionTemplate> result = v8::FunctionTemplate::New(USE_CALLBACK(HTMLImageElementConstructor)); v8::Local<v8::ObjectTemplate> instance = result->InstanceTemplate(); - instance->SetInternalFieldCount(V8Custom::kNodeMinimumInternalFieldCount); + instance->SetInternalFieldCount(V8HTMLImageElement::internalFieldCount); result->SetClassName(v8::String::New("HTMLImageElement")); result->Inherit(V8DOMWrapper::getTemplate(V8ClassIndex::HTMLIMAGEELEMENT)); @@ -61,7 +61,7 @@ v8::Persistent<v8::FunctionTemplate> V8HTMLImageElementConstructor::GetTemplate( return cachedTemplate; } -CALLBACK_FUNC_DECL(HTMLImageElementConstructor) +v8::Handle<v8::Value> V8Custom::v8HTMLImageElementConstructorCallback(const v8::Arguments& args) { INC_STATS("DOM.HTMLImageElement.Contructor"); diff --git a/WebCore/bindings/v8/custom/V8HTMLInputElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLInputElementCustom.cpp index 63fbcec..78486b3 100644 --- a/WebCore/bindings/v8/custom/V8HTMLInputElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLInputElementCustom.cpp @@ -29,6 +29,8 @@ */ #include "config.h" +#include "V8HTMLInputElement.h" + #include "HTMLInputElement.h" #include "V8Binding.h" @@ -37,11 +39,11 @@ namespace WebCore { -ACCESSOR_GETTER(HTMLInputElementSelectionStart) +v8::Handle<v8::Value> V8HTMLInputElement::selectionStartAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.HTMLInputElement.selectionStart._get"); v8::Handle<v8::Object> holder = info.Holder(); - HTMLInputElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLInputElement>(holder); + HTMLInputElement* imp = V8HTMLInputElement::toNative(holder); if (!imp->canHaveSelection()) return throwError("Accessing selectionStart on an input element that cannot have a selection."); @@ -50,11 +52,11 @@ ACCESSOR_GETTER(HTMLInputElementSelectionStart) return v8::Integer::New(v); } -ACCESSOR_SETTER(HTMLInputElementSelectionStart) +void V8HTMLInputElement::selectionStartAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { INC_STATS("DOM.HTMLInputElement.selectionStart._set"); v8::Handle<v8::Object> holder = info.Holder(); - HTMLInputElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLInputElement>(holder); + HTMLInputElement* imp = V8HTMLInputElement::toNative(holder); if (!imp->canHaveSelection()) { throwError("Accessing selectionStart on an input element that cannot have a selection."); @@ -63,11 +65,11 @@ ACCESSOR_SETTER(HTMLInputElementSelectionStart) imp->setSelectionStart(value->Int32Value()); } -ACCESSOR_GETTER(HTMLInputElementSelectionEnd) +v8::Handle<v8::Value> V8HTMLInputElement::selectionEndAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.HTMLInputElement.selectionEnd._get"); v8::Handle<v8::Object> holder = info.Holder(); - HTMLInputElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLInputElement>(holder); + HTMLInputElement* imp = V8HTMLInputElement::toNative(holder); if (!imp->canHaveSelection()) return throwError("Accessing selectionEnd on an input element that cannot have a selection."); @@ -76,11 +78,11 @@ ACCESSOR_GETTER(HTMLInputElementSelectionEnd) return v8::Integer::New(v); } -ACCESSOR_SETTER(HTMLInputElementSelectionEnd) +void V8HTMLInputElement::selectionEndAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { INC_STATS("DOM.HTMLInputElement.selectionEnd._set"); v8::Handle<v8::Object> holder = info.Holder(); - HTMLInputElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLInputElement>(holder); + HTMLInputElement* imp = V8HTMLInputElement::toNative(holder); if (!imp->canHaveSelection()) { throwError("Accessing selectionEnd on an input element that cannot have a selection."); @@ -90,11 +92,11 @@ ACCESSOR_SETTER(HTMLInputElementSelectionEnd) imp->setSelectionEnd(value->Int32Value()); } -CALLBACK_FUNC_DECL(HTMLInputElementSetSelectionRange) +v8::Handle<v8::Value> V8HTMLInputElement::setSelectionRangeCallback(const v8::Arguments& args) { INC_STATS("DOM.HTMLInputElement.setSelectionRange"); v8::Handle<v8::Object> holder = args.Holder(); - HTMLInputElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLInputElement>(holder); + HTMLInputElement* imp = V8HTMLInputElement::toNative(holder); if (!imp->canHaveSelection()) return throwError("Calling setSelectionRange on an input element that cannot have a selection."); diff --git a/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp b/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp index f9c9cb4..5325933 100644 --- a/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp @@ -36,8 +36,8 @@ #include "Frame.h" #include "HTMLNames.h" #include "Text.h" - #include "V8Binding.h" +#include "V8HTMLOptionElement.h" #include "V8Proxy.h" #include <wtf/RefPtr.h> @@ -54,7 +54,7 @@ v8::Persistent<v8::FunctionTemplate> V8HTMLOptionElementConstructor::GetTemplate v8::Local<v8::FunctionTemplate> result = v8::FunctionTemplate::New(USE_CALLBACK(HTMLOptionElementConstructor)); v8::Local<v8::ObjectTemplate> instance = result->InstanceTemplate(); - instance->SetInternalFieldCount(V8Custom::kNodeMinimumInternalFieldCount); + instance->SetInternalFieldCount(V8HTMLOptionElement::internalFieldCount); result->SetClassName(v8::String::New("HTMLOptionElement")); result->Inherit(V8DOMWrapper::getTemplate(V8ClassIndex::HTMLOPTIONELEMENT)); @@ -62,7 +62,7 @@ v8::Persistent<v8::FunctionTemplate> V8HTMLOptionElementConstructor::GetTemplate return cachedTemplate; } -CALLBACK_FUNC_DECL(HTMLOptionElementConstructor) +v8::Handle<v8::Value> V8Custom::v8HTMLOptionElementConstructorCallback(const v8::Arguments& args) { INC_STATS("DOM.HTMLOptionElement.Contructor"); diff --git a/WebCore/bindings/v8/custom/V8HTMLOptionsCollectionCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLOptionsCollectionCustom.cpp index 02c3499..c060df7 100644 --- a/WebCore/bindings/v8/custom/V8HTMLOptionsCollectionCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLOptionsCollectionCustom.cpp @@ -29,8 +29,9 @@ */ #include "config.h" -#include "HTMLOptionsCollection.h" +#include "V8HTMLOptionsCollection.h" +#include "HTMLOptionsCollection.h" #include "HTMLOptionElement.h" #include "ExceptionCode.h" @@ -43,23 +44,23 @@ namespace WebCore { -CALLBACK_FUNC_DECL(HTMLOptionsCollectionRemove) +v8::Handle<v8::Value> V8HTMLOptionsCollection::removeCallback(const v8::Arguments& args) { INC_STATS("DOM.HTMLOptionsCollection.remove()"); - HTMLOptionsCollection* imp = V8DOMWrapper::convertToNativeObject<HTMLOptionsCollection>(V8ClassIndex::HTMLOPTIONSCOLLECTION, args.Holder()); + HTMLOptionsCollection* imp = V8HTMLOptionsCollection::toNative(args.Holder()); HTMLSelectElement* base = static_cast<HTMLSelectElement*>(imp->base()); return removeElement(base, args); } -CALLBACK_FUNC_DECL(HTMLOptionsCollectionAdd) +v8::Handle<v8::Value> V8HTMLOptionsCollection::addCallback(const v8::Arguments& args) { INC_STATS("DOM.HTMLOptionsCollection.add()"); if (!V8HTMLOptionElement::HasInstance(args[0])) { V8Proxy::setDOMException(TYPE_MISMATCH_ERR); return v8::Undefined(); } - HTMLOptionsCollection* imp = V8DOMWrapper::convertToNativeObject<HTMLOptionsCollection>(V8ClassIndex::HTMLOPTIONSCOLLECTION, args.Holder()); - HTMLOptionElement* option = V8DOMWrapper::convertDOMWrapperToNode<HTMLOptionElement>(v8::Handle<v8::Object>(v8::Handle<v8::Object>::Cast(args[0]))); + HTMLOptionsCollection* imp = V8HTMLOptionsCollection::toNative(args.Holder()); + HTMLOptionElement* option = V8HTMLOptionElement::toNative(v8::Handle<v8::Object>(v8::Handle<v8::Object>::Cast(args[0]))); ExceptionCode ec = 0; if (args.Length() < 2) @@ -84,18 +85,18 @@ CALLBACK_FUNC_DECL(HTMLOptionsCollectionAdd) return v8::Undefined(); } -ACCESSOR_GETTER(HTMLOptionsCollectionLength) +v8::Handle<v8::Value> V8HTMLOptionsCollection::lengthAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.HTMLOptionsCollection.length._get"); - HTMLOptionsCollection* imp = V8DOMWrapper::convertToNativeObject<HTMLOptionsCollection>(V8ClassIndex::HTMLOPTIONSCOLLECTION, info.Holder()); + HTMLOptionsCollection* imp = V8HTMLOptionsCollection::toNative(info.Holder()); int v = imp->length(); return v8::Integer::New(v); } -ACCESSOR_SETTER(HTMLOptionsCollectionLength) +void V8HTMLOptionsCollection::lengthAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { INC_STATS("DOM.HTMLOptionsCollection.length._set"); - HTMLOptionsCollection* imp = V8DOMWrapper::convertToNativeObject<HTMLOptionsCollection>(V8ClassIndex::HTMLOPTIONSCOLLECTION, info.Holder()); + HTMLOptionsCollection* imp = V8HTMLOptionsCollection::toNative(info.Holder()); double v = value->NumberValue(); unsigned newLength = 0; ExceptionCode ec = 0; @@ -113,10 +114,10 @@ ACCESSOR_SETTER(HTMLOptionsCollectionLength) V8Proxy::setDOMException(ec); } -INDEXED_PROPERTY_GETTER(HTMLOptionsCollection) +v8::Handle<v8::Value> V8HTMLOptionsCollection::indexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info) { INC_STATS("DOM.HTMLOptionsCollection.IndexedPropertyGetter"); - HTMLOptionsCollection* collection = V8DOMWrapper::convertToNativeObject<HTMLOptionsCollection>(V8ClassIndex::HTMLOPTIONSCOLLECTION, info.Holder()); + HTMLOptionsCollection* collection = V8HTMLOptionsCollection::toNative(info.Holder()); RefPtr<Node> result = collection->item(index); if (!result) @@ -125,10 +126,10 @@ INDEXED_PROPERTY_GETTER(HTMLOptionsCollection) return V8DOMWrapper::convertNodeToV8Object(result.release()); } -INDEXED_PROPERTY_SETTER(HTMLOptionsCollection) +v8::Handle<v8::Value> V8HTMLOptionsCollection::indexedPropertySetter(uint32_t index, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { INC_STATS("DOM.HTMLOptionsCollection.IndexedPropertySetter"); - HTMLOptionsCollection* collection = V8DOMWrapper::convertToNativeObject<HTMLOptionsCollection>(V8ClassIndex::HTMLOPTIONSCOLLECTION, info.Holder()); + HTMLOptionsCollection* collection = V8HTMLOptionsCollection::toNative(info.Holder()); HTMLSelectElement* base = static_cast<HTMLSelectElement*>(collection->base()); return toOptionsCollectionSetter(index, value, base); } diff --git a/WebCore/bindings/v8/custom/V8HTMLPlugInElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLPlugInElementCustom.cpp index 13c82f3..261b5a8 100644 --- a/WebCore/bindings/v8/custom/V8HTMLPlugInElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLPlugInElementCustom.cpp @@ -32,18 +32,23 @@ #include "HTMLPlugInElement.h" #include "ScriptInstance.h" - #include "V8Binding.h" #include "V8CustomBinding.h" +#include "V8HTMLAppletElement.h" +#include "V8HTMLEmbedElement.h" +#include "V8HTMLObjectElement.h" #include "V8NPObject.h" #include "V8Proxy.h" namespace WebCore { -NAMED_PROPERTY_GETTER(HTMLPlugInElement) +// FIXME: Consider moving getter/setter helpers to V8NPObject and renaming this file to V8PluginElementFunctions +// to match JSC bindings naming convention. + +template <class C> +static v8::Handle<v8::Value> npObjectNamedGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { - INC_STATS("DOM.HTMLPlugInElement.NamedPropertyGetter"); - HTMLPlugInElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLPlugInElement>(info.Holder()); + HTMLPlugInElement* imp = C::toNative(info.Holder()); ScriptInstance scriptInstance = imp->getInstance(); if (!scriptInstance) return notHandledByInterceptor(); @@ -55,10 +60,10 @@ NAMED_PROPERTY_GETTER(HTMLPlugInElement) return npObjectGetNamedProperty(instance, name); } -NAMED_PROPERTY_SETTER(HTMLPlugInElement) +template <class C> +static v8::Handle<v8::Value> npObjectNamedSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { - INC_STATS("DOM.HTMLPlugInElement.NamedPropertySetter"); - HTMLPlugInElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLPlugInElement>(info.Holder()); + HTMLPlugInElement* imp = C::toNative(info.Holder()); ScriptInstance scriptInstance = imp->getInstance(); if (!scriptInstance) return notHandledByInterceptor(); @@ -70,16 +75,65 @@ NAMED_PROPERTY_SETTER(HTMLPlugInElement) return npObjectSetNamedProperty(instance, name, value); } -CALLBACK_FUNC_DECL(HTMLPlugInElement) +v8::Handle<v8::Value> V8HTMLAppletElement::namedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.HTMLAppletElement.NamedPropertyGetter"); + return npObjectNamedGetter<V8HTMLAppletElement>(name, info); +} + +v8::Handle<v8::Value> V8HTMLEmbedElement::namedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.HTMLEmbedElement.NamedPropertyGetter"); + return npObjectNamedGetter<V8HTMLEmbedElement>(name, info); +} + +v8::Handle<v8::Value> V8HTMLObjectElement::namedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.HTMLObjectElement.NamedPropertyGetter"); + return npObjectNamedGetter<V8HTMLObjectElement>(name, info); +} + +v8::Handle<v8::Value> V8HTMLAppletElement::namedPropertySetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.HTMLAppletElement.NamedPropertySetter"); + return npObjectNamedSetter<V8HTMLAppletElement>(name, value, info); +} + +v8::Handle<v8::Value> V8HTMLEmbedElement::namedPropertySetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.HTMLEmbedElement.NamedPropertySetter"); + return npObjectNamedSetter<V8HTMLEmbedElement>(name, value, info); +} + +v8::Handle<v8::Value> V8HTMLObjectElement::namedPropertySetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.HTMLObjectElement.NamedPropertySetter"); + return npObjectNamedSetter<V8HTMLObjectElement>(name, value, info); +} + +v8::Handle<v8::Value> V8HTMLAppletElement::callAsFunctionCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.HTMLAppletElement()"); + return npObjectInvokeDefaultHandler(args); +} + +v8::Handle<v8::Value> V8HTMLEmbedElement::callAsFunctionCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.HTMLEmbedElement()"); + return npObjectInvokeDefaultHandler(args); +} + +v8::Handle<v8::Value> V8HTMLObjectElement::callAsFunctionCallback(const v8::Arguments& args) { - INC_STATS("DOM.HTMLPluginElement()"); + INC_STATS("DOM.HTMLObjectElement()"); return npObjectInvokeDefaultHandler(args); } -INDEXED_PROPERTY_GETTER(HTMLPlugInElement) +template <class C> +v8::Handle<v8::Value> npObjectIndexedGetter(uint32_t index, const v8::AccessorInfo& info) { INC_STATS("DOM.HTMLPlugInElement.IndexedPropertyGetter"); - HTMLPlugInElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLPlugInElement>(info.Holder()); + HTMLPlugInElement* imp = C::toNative(info.Holder()); ScriptInstance scriptInstance = imp->getInstance(); if (!scriptInstance) return notHandledByInterceptor(); @@ -91,10 +145,11 @@ INDEXED_PROPERTY_GETTER(HTMLPlugInElement) return npObjectGetIndexedProperty(instance, index); } -INDEXED_PROPERTY_SETTER(HTMLPlugInElement) +template <class C> +v8::Handle<v8::Value> npObjectIndexedSetter(uint32_t index, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { INC_STATS("DOM.HTMLPlugInElement.IndexedPropertySetter"); - HTMLPlugInElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLPlugInElement>(info.Holder()); + HTMLPlugInElement* imp = C::toNative(info.Holder()); ScriptInstance scriptInstance = imp->getInstance(); if (!scriptInstance) return notHandledByInterceptor(); @@ -106,4 +161,40 @@ INDEXED_PROPERTY_SETTER(HTMLPlugInElement) return npObjectSetIndexedProperty(instance, index, value); } +v8::Handle<v8::Value> V8HTMLAppletElement::indexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.HTMLAppletElement.IndexedPropertyGetter"); + return npObjectIndexedGetter<V8HTMLAppletElement>(index, info); +} + +v8::Handle<v8::Value> V8HTMLEmbedElement::indexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.HTMLEmbedElement.IndexedPropertyGetter"); + return npObjectIndexedGetter<V8HTMLEmbedElement>(index, info); +} + +v8::Handle<v8::Value> V8HTMLObjectElement::indexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.HTMLObjectElement.IndexedPropertyGetter"); + return npObjectIndexedGetter<V8HTMLObjectElement>(index, info); +} + +v8::Handle<v8::Value> V8HTMLAppletElement::indexedPropertySetter(uint32_t index, v8::Local<v8::Value> value, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.HTMLAppletElement.IndexedPropertySetter"); + return npObjectIndexedSetter<V8HTMLAppletElement>(index, value, info); +} + +v8::Handle<v8::Value> V8HTMLEmbedElement::indexedPropertySetter(uint32_t index, v8::Local<v8::Value> value, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.HTMLEmbedElement.IndexedPropertySetter"); + return npObjectIndexedSetter<V8HTMLEmbedElement>(index, value, info); +} + +v8::Handle<v8::Value> V8HTMLObjectElement::indexedPropertySetter(uint32_t index, v8::Local<v8::Value> value, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.HTMLObjectElement.IndexedPropertySetter"); + return npObjectIndexedSetter<V8HTMLObjectElement>(index, value, info); +} + } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8HTMLSelectElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLSelectElementCustom.cpp index 661ffa2..0904b3e 100644 --- a/WebCore/bindings/v8/custom/V8HTMLSelectElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLSelectElementCustom.cpp @@ -33,25 +33,75 @@ #include "HTMLSelectElement.h" #include "HTMLOptionElement.h" +#include "HTMLOptionsCollection.h" #include "V8Binding.h" +#include "V8Collection.h" #include "V8CustomBinding.h" #include "V8HTMLOptionElement.h" +#include "V8HTMLSelectElement.h" +#include "V8NamedNodesCollection.h" #include "V8Proxy.h" namespace WebCore { -CALLBACK_FUNC_DECL(HTMLSelectElementRemove) +v8::Handle<v8::Value> V8HTMLSelectElement::namedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.HTMLSelectElement.NamedPropertyGetter"); + HTMLSelectElement* select = V8HTMLSelectElement::toNative(info.Holder()); + v8::Handle<v8::Value> value = info.Holder()->GetRealNamedPropertyInPrototypeChain(name); + + if (!value.IsEmpty()) + return value; + + // Search local callback properties next to find IDL defined properties. + if (info.Holder()->HasRealNamedCallbackProperty(name)) + return notHandledByInterceptor(); + + PassRefPtr<HTMLOptionsCollection> collection = select->options(); + + Vector<RefPtr<Node> > items; + collection->namedItems(v8StringToAtomicWebCoreString(name), items); + + if (!items.size()) + return notHandledByInterceptor(); + + if (items.size() == 1) + return V8DOMWrapper::convertNodeToV8Object(items.at(0).release()); + + NodeList* list = new V8NamedNodesCollection(items); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::NODELIST, list); +} + +v8::Handle<v8::Value> V8HTMLSelectElement::indexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info) +{ + ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder())); + ASSERT(V8DOMWrapper::domWrapperType(info.Holder()) == V8ClassIndex::NODE); + RefPtr<Node> result = V8HTMLSelectElement::toNative(info.Holder())->item(index); + if (!result) + return notHandledByInterceptor(); + + return V8DOMWrapper::convertNodeToV8Object(result.release()); +} + +v8::Handle<v8::Value> V8HTMLSelectElement::indexedPropertySetter(uint32_t index, v8::Local<v8::Value> value, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.HTMLSelectElement.IndexedPropertySetter"); + HTMLSelectElement* select = V8HTMLSelectElement::toNative(info.Holder()); + return toOptionsCollectionSetter(index, value, select); +} + +v8::Handle<v8::Value> V8HTMLSelectElement::removeCallback(const v8::Arguments& args) { INC_STATS("DOM.HTMLSelectElement.remove"); - HTMLSelectElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLSelectElement>(args.Holder()); + HTMLSelectElement* imp = V8HTMLSelectElement::toNative(args.Holder()); return removeElement(imp, args); } v8::Handle<v8::Value> removeElement(HTMLSelectElement* imp, const v8::Arguments& args) { if (V8HTMLOptionElement::HasInstance(args[0])) { - HTMLOptionElement* element = V8DOMWrapper::convertDOMWrapperToNode<HTMLOptionElement>(v8::Handle<v8::Object>::Cast(args[0])); + HTMLOptionElement* element = V8HTMLOptionElement::toNative(v8::Handle<v8::Object>::Cast(args[0])); imp->remove(element->index()); return v8::Undefined(); } diff --git a/WebCore/bindings/v8/custom/V8HistoryCustom.cpp b/WebCore/bindings/v8/custom/V8HistoryCustom.cpp index c884d15..b857d6e 100644 --- a/WebCore/bindings/v8/custom/V8HistoryCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HistoryCustom.cpp @@ -29,18 +29,21 @@ */ #include "config.h" -#include "History.h" +#include "V8History.h" #include "ExceptionCode.h" +#include "History.h" #include "SerializedScriptValue.h" #include "V8Binding.h" +#include "V8BindingState.h" #include "V8CustomBinding.h" #include "V8Proxy.h" namespace WebCore { -CALLBACK_FUNC_DECL(HistoryPushState) + +v8::Handle<v8::Value> V8History::pushStateCallback(const v8::Arguments& args) { - RefPtr<SerializedScriptValue> historyState = SerializedScriptValue::create(toWebCoreString(args[0])); + RefPtr<SerializedScriptValue> historyState = SerializedScriptValue::create(args[0]); v8::TryCatch tryCatch; String title = toWebCoreStringWithNullOrUndefinedCheck(args[1]); @@ -54,14 +57,14 @@ CALLBACK_FUNC_DECL(HistoryPushState) } ExceptionCode ec = 0; - History* history = V8DOMWrapper::convertToNativeObject<History>(V8ClassIndex::HISTORY, args.Holder()); + History* history = V8History::toNative(args.Holder()); history->stateObjectAdded(historyState.release(), title, url, History::StateObjectPush, ec); return throwError(ec); } -CALLBACK_FUNC_DECL(HistoryReplaceState) +v8::Handle<v8::Value> V8History::replaceStateCallback(const v8::Arguments& args) { - RefPtr<SerializedScriptValue> historyState = SerializedScriptValue::create(toWebCoreString(args[0])); + RefPtr<SerializedScriptValue> historyState = SerializedScriptValue::create(args[0]); v8::TryCatch tryCatch; String title = toWebCoreStringWithNullOrUndefinedCheck(args[1]); @@ -75,9 +78,25 @@ CALLBACK_FUNC_DECL(HistoryReplaceState) } ExceptionCode ec = 0; - History* history = V8DOMWrapper::convertToNativeObject<History>(V8ClassIndex::HISTORY, args.Holder()); + History* history = V8History::toNative(args.Holder()); history->stateObjectAdded(historyState.release(), title, url, History::StateObjectReplace, ec); return throwError(ec); } +bool V8History::indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType type, v8::Local<v8::Value> data) +{ + 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) +{ + 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); +} + } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8FileListCustom.cpp b/WebCore/bindings/v8/custom/V8IDBRequestCustom.cpp index bc533cf..5ee9542 100644 --- a/WebCore/bindings/v8/custom/V8FileListCustom.cpp +++ b/WebCore/bindings/v8/custom/V8IDBRequestCustom.cpp @@ -1,5 +1,5 @@ /* - * 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 @@ -29,26 +29,21 @@ */ #include "config.h" -#include "FileList.h" +#include "V8IDBRequest.h" -#include "File.h" -#include "V8Binding.h" -#include "V8CustomBinding.h" +#include "SerializedScriptValue.h" #include "V8Proxy.h" -#include <wtf/RefPtr.h> - namespace WebCore { -INDEXED_PROPERTY_GETTER(FileList) +v8::Handle<v8::Value> V8IDBRequest::resultAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { - INC_STATS("DOM.FileList.IndexedPropertyGetter"); - FileList* fileList = V8DOMWrapper::convertToNativeObject<FileList>(V8ClassIndex::FILELIST, info.Holder()); - RefPtr<File> file = fileList->item(index); - if (!file) - return notHandledByInterceptor(); + IDBRequest* request = V8IDBRequest::toNative(info.Holder()); + SerializedScriptValue* result = request->result(); + if (!result) + return v8::Null(); - return V8DOMWrapper::convertToV8Object(V8ClassIndex::FILE, file.release()); + return result->deserialize(); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8IndexedDatabaseRequestCustom.cpp b/WebCore/bindings/v8/custom/V8IndexedDatabaseRequestCustom.cpp new file mode 100644 index 0000000..66220ea --- /dev/null +++ b/WebCore/bindings/v8/custom/V8IndexedDatabaseRequestCustom.cpp @@ -0,0 +1,57 @@ +/* + * 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 "V8IndexedDatabaseRequest.h" + +#include "V8Binding.h" +#include "V8Proxy.h" + +namespace WebCore { + +v8::Handle<v8::Value> V8IndexedDatabaseRequest::openCallback(const v8::Arguments& args) +{ + IndexedDatabaseRequest* imp = V8IndexedDatabaseRequest::toNative(args.Holder()); + if (args.Length() < 2) + return throwError(V8Proxy::TypeError); + V8Parameter<> name = args[0]; + V8Parameter<> description = args[1]; + bool modifyDatabase = true; + if (args.Length() > 2) + modifyDatabase = args[2]->BooleanValue(); + + ExceptionCode ec = 0; + imp->open(name, description, modifyDatabase, ec); + if (ec) + return throwError(ec); + return v8::Handle<v8::Value>(); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp b/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp index fac6733..0ddcf97 100644 --- a/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp +++ b/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp @@ -29,45 +29,98 @@ */ #include "config.h" -#include "InjectedScriptHost.h" +#include "V8InjectedScriptHost.h" -#include "Database.h" #include "DOMWindow.h" +#include "Database.h" #include "Frame.h" +#include "InjectedScriptHost.h" #include "InspectorController.h" #include "Node.h" #include "Page.h" #include "V8Binding.h" #include "V8CustomBinding.h" +#include "V8Database.h" +#include "V8Node.h" #include "V8Proxy.h" +#include "V8Storage.h" namespace WebCore { -CALLBACK_FUNC_DECL(InjectedScriptHostInspectedWindow) +static void WeakReferenceCallback(v8::Persistent<v8::Value> object, void* parameter) { - INC_STATS("InjectedScriptHost.inspectedWindow()"); + InjectedScriptHost* nativeObject = static_cast<InjectedScriptHost*>(parameter); + nativeObject->deref(); + object.Dispose(); +} - InjectedScriptHost* host = V8DOMWrapper::convertToNativeObject<InjectedScriptHost>(V8ClassIndex::INJECTEDSCRIPTHOST, args.Holder()); - InspectorController* ic = host->inspectorController(); - if (!ic) - return v8::Undefined(); - return V8DOMWrapper::convertToV8Object<DOMWindow>(V8ClassIndex::DOMWINDOW, ic->inspectedPage()->mainFrame()->domWindow()); +static v8::Local<v8::Object> createInjectedScriptHostV8Wrapper(InjectedScriptHost* host) +{ + V8ClassIndex::V8WrapperType descriptorType = V8ClassIndex::INJECTEDSCRIPTHOST; + v8::Local<v8::Function> function = V8DOMWrapper::getTemplate(descriptorType)->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>(); + } + V8DOMWrapper::setDOMWrapper(instance, V8ClassIndex::ToInt(descriptorType), host); + // Create a weak reference to the v8 wrapper of InspectorBackend to deref + // InspectorBackend when the wrapper is garbage collected. + host->ref(); + v8::Persistent<v8::Object> weakHandle = v8::Persistent<v8::Object>::New(instance); + weakHandle.MakeWeak(host, &WeakReferenceCallback); + return instance; } -CALLBACK_FUNC_DECL(InjectedScriptHostWrapCallback) +static ScriptObject createInjectedScript(const String& scriptSource, InjectedScriptHost* injectedScriptHost, ScriptState* inspectedScriptState, long id) { - INC_STATS("InjectedScriptHost.wrapCallback()"); - return args[0]; + v8::HandleScope scope; + + v8::Local<v8::Context> inspectedContext = inspectedScriptState->context(); + v8::Context::Scope contextScope(inspectedContext); + + // Call custom code to create InjectedScripHost wrapper specific for the context + // instead of calling V8DOMWrapper::convertToV8Object 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); + if (scriptHostWrapper.IsEmpty()) + return ScriptObject(); + + v8::Local<v8::Object> windowGlobal = inspectedContext->Global(); + + // Inject javascript into the context. The compiled script is supposed to evaluate into + // a single anonymous function(it's anonymous to avoid cluttering the global object with + // inspector's stuff) the function is called a few lines below with InjectedScriptHost wrapper, + // injected script id and explicit reference to the inspected global object. The function is expected + // to create and configure InjectedScript instance that is going to be used by the inspector. + v8::Local<v8::Script> script = v8::Script::Compile(v8String(scriptSource)); + v8::Local<v8::Value> v = script->Run(); + ASSERT(!v.IsEmpty()); + ASSERT(v->IsFunction()); + + v8::Handle<v8::Value> args[] = { + scriptHostWrapper, + windowGlobal, + v8::Number::New(id) + }; + v8::Local<v8::Value> injectedScriptValue = v8::Function::Cast(*v)->Call(windowGlobal, 3, args); + v8::Local<v8::Object> injectedScript(v8::Object::Cast(*injectedScriptValue)); + return ScriptObject(inspectedScriptState, injectedScript); } -CALLBACK_FUNC_DECL(InjectedScriptHostNodeForId) +v8::Handle<v8::Value> V8InjectedScriptHost::nodeForIdCallback(const v8::Arguments& args) { INC_STATS("InjectedScriptHost.nodeForId()"); if (args.Length() < 1) return v8::Undefined(); - InjectedScriptHost* host = V8DOMWrapper::convertToNativeObject<InjectedScriptHost>(V8ClassIndex::INJECTEDSCRIPTHOST, args.Holder()); + InjectedScriptHost* host = V8InjectedScriptHost::toNative(args.Holder()); Node* node = host->nodeForId(args[0]->ToInt32()->Value()); if (!node) @@ -80,63 +133,44 @@ CALLBACK_FUNC_DECL(InjectedScriptHostNodeForId) return V8DOMWrapper::convertToV8Object(V8ClassIndex::NODE, node); } -CALLBACK_FUNC_DECL(InjectedScriptHostWrapObject) -{ - INC_STATS("InjectedScriptHost.wrapObject()"); - if (args.Length() < 2) - return v8::Undefined(); - - InjectedScriptHost* host = V8DOMWrapper::convertToNativeObject<InjectedScriptHost>(V8ClassIndex::INJECTEDSCRIPTHOST, args.Holder()); - return host->wrapObject(ScriptValue(args[0]), toWebCoreStringWithNullCheck(args[1])).v8Value(); -} - -CALLBACK_FUNC_DECL(InjectedScriptHostUnwrapObject) -{ - INC_STATS("InjectedScriptHost.unwrapObject()"); - if (args.Length() < 1) - return v8::Undefined(); - - InjectedScriptHost* host = V8DOMWrapper::convertToNativeObject<InjectedScriptHost>(V8ClassIndex::INJECTEDSCRIPTHOST, args.Holder()); - return host->unwrapObject(toWebCoreStringWithNullCheck(args[0])).v8Value(); -} - -CALLBACK_FUNC_DECL(InjectedScriptHostPushNodePathToFrontend) +v8::Handle<v8::Value> V8InjectedScriptHost::pushNodePathToFrontendCallback(const v8::Arguments& args) { INC_STATS("InjectedScriptHost.pushNodePathToFrontend()"); - if (args.Length() < 2) + if (args.Length() < 3) return v8::Undefined(); - InjectedScriptHost* host = V8DOMWrapper::convertToNativeObject<InjectedScriptHost>(V8ClassIndex::INJECTEDSCRIPTHOST, args.Holder()); - Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])); - bool selectInUI = args[1]->ToBoolean()->Value(); + InjectedScriptHost* host = V8InjectedScriptHost::toNative(args.Holder()); + Node* node = V8Node::toNative(v8::Handle<v8::Object>::Cast(args[0])); + bool withChildren = args[1]->ToBoolean()->Value(); + bool selectInUI = args[2]->ToBoolean()->Value(); if (node) - return v8::Number::New(host->pushNodePathToFrontend(node, selectInUI)); + return v8::Number::New(host->pushNodePathToFrontend(node, withChildren, selectInUI)); return v8::Undefined(); } #if ENABLE(DATABASE) -CALLBACK_FUNC_DECL(InjectedScriptHostDatabaseForId) +v8::Handle<v8::Value> V8InjectedScriptHost::databaseForIdCallback(const v8::Arguments& args) { INC_STATS("InjectedScriptHost.databaseForId()"); if (args.Length() < 1) return v8::Undefined(); - InjectedScriptHost* host = V8DOMWrapper::convertToNativeObject<InjectedScriptHost>(V8ClassIndex::INJECTEDSCRIPTHOST, args.Holder()); + InjectedScriptHost* host = V8InjectedScriptHost::toNative(args.Holder()); Database* database = host->databaseForId(args[0]->ToInt32()->Value()); if (!database) return v8::Undefined(); return V8DOMWrapper::convertToV8Object<Database>(V8ClassIndex::DATABASE, database); } -CALLBACK_FUNC_DECL(InjectedScriptHostSelectDatabase) +v8::Handle<v8::Value> V8InjectedScriptHost::selectDatabaseCallback(const v8::Arguments& args) { INC_STATS("InjectedScriptHost.selectDatabase()"); if (args.Length() < 1) return v8::Undefined(); - InjectedScriptHost* host = V8DOMWrapper::convertToNativeObject<InjectedScriptHost>(V8ClassIndex::INJECTEDSCRIPTHOST, args.Holder()); - Database* database = V8DOMWrapper::convertToNativeObject<Database>(V8ClassIndex::DATABASE, v8::Handle<v8::Object>::Cast(args[0])); + InjectedScriptHost* host = V8InjectedScriptHost::toNative(args.Holder()); + Database* database = V8Database::toNative(v8::Handle<v8::Object>::Cast(args[0])); if (database) host->selectDatabase(database); @@ -145,14 +179,14 @@ CALLBACK_FUNC_DECL(InjectedScriptHostSelectDatabase) #endif #if ENABLE(DOM_STORAGE) -CALLBACK_FUNC_DECL(InjectedScriptHostSelectDOMStorage) +v8::Handle<v8::Value> V8InjectedScriptHost::selectDOMStorageCallback(const v8::Arguments& args) { INC_STATS("InjectedScriptHost.selectDOMStorage()"); if (args.Length() < 1) return v8::Undefined(); - InjectedScriptHost* host = V8DOMWrapper::convertToNativeObject<InjectedScriptHost>(V8ClassIndex::INJECTEDSCRIPTHOST, args.Holder()); - Storage* storage = V8DOMWrapper::convertToNativeObject<Storage>(V8ClassIndex::STORAGE, v8::Handle<v8::Object>::Cast(args[0])); + InjectedScriptHost* host = V8InjectedScriptHost::toNative(args.Holder()); + Storage* storage = V8Storage::toNative(v8::Handle<v8::Object>::Cast(args[0])); if (storage) host->selectDOMStorage(storage); @@ -160,4 +194,28 @@ CALLBACK_FUNC_DECL(InjectedScriptHostSelectDOMStorage) } #endif +ScriptObject InjectedScriptHost::injectedScriptFor(ScriptState* inspectedScriptState) +{ + v8::HandleScope handleScope; + v8::Local<v8::Context> context = inspectedScriptState->context(); + v8::Context::Scope contextScope(context); + + v8::Local<v8::Object> global = context->Global(); + // Skip proxy object. The proxy object will survive page navigation while we need + // an object whose lifetime consides with that of the inspected context. + global = v8::Local<v8::Object>::Cast(global->GetPrototype()); + + v8::Local<v8::String> key = v8::String::New("Devtools_InjectedScript"); + v8::Local<v8::Value> val = global->GetHiddenValue(key); + if (!val.IsEmpty() && val->IsObject()) + return ScriptObject(inspectedScriptState, v8::Local<v8::Object>::Cast(val)); + + ASSERT(!m_injectedScriptSource.isEmpty()); + ScriptObject injectedScriptObject = createInjectedScript(m_injectedScriptSource, this, inspectedScriptState, m_nextInjectedScriptId); + m_idToInjectedScript.set(m_nextInjectedScriptId, injectedScriptObject); + ++m_nextInjectedScriptId; + global->SetHiddenValue(key, injectedScriptObject.v8Object()); + return injectedScriptObject; +} + } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8InspectorFrontendHostCustom.cpp b/WebCore/bindings/v8/custom/V8InspectorFrontendHostCustom.cpp index 15b45e9..df63bf1 100644 --- a/WebCore/bindings/v8/custom/V8InspectorFrontendHostCustom.cpp +++ b/WebCore/bindings/v8/custom/V8InspectorFrontendHostCustom.cpp @@ -29,15 +29,10 @@ */ #include "config.h" -#include "InspectorFrontendHost.h" +#include "V8InspectorFrontendHost.h" -#include "ExceptionCode.h" #include "InspectorController.h" -#include "Node.h" -#include "Range.h" -#include "Page.h" -#include "TextIterator.h" -#include "VisiblePosition.h" +#include "InspectorFrontendHost.h" #include "V8Binding.h" #include "V8CustomBinding.h" @@ -45,46 +40,7 @@ namespace WebCore { -CALLBACK_FUNC_DECL(InspectorFrontendHostSearch) -{ - INC_STATS("InspectorFrontendHost.search()"); - - if (args.Length() < 2) - return v8::Undefined(); - - Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])); - if (!node) - return v8::Undefined(); - - String target = toWebCoreStringWithNullCheck(args[1]); - if (target.isEmpty()) - return v8::Undefined(); - - v8::Local<v8::Array> result = v8::Array::New(); - RefPtr<Range> searchRange(rangeOfContents(node)); - - ExceptionCode ec = 0; - int index = 0; - do { - RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, true, false)); - if (resultRange->collapsed(ec)) - break; - - // A non-collapsed result range can in some funky whitespace cases still not - // advance the range's start position (4509328). Break to avoid infinite loop. - VisiblePosition newStart = endVisiblePosition(resultRange.get(), DOWNSTREAM); - if (newStart == startVisiblePosition(searchRange.get(), DOWNSTREAM)) - break; - - result->Set(v8::Number::New(index++), V8DOMWrapper::convertToV8Object(V8ClassIndex::RANGE, resultRange.release())); - - setStart(searchRange.get(), newStart); - } while (true); - - return result; -} - -CALLBACK_FUNC_DECL(InspectorFrontendHostShowContextMenu) +v8::Handle<v8::Value> V8InspectorFrontendHost::showContextMenuCallback(const v8::Arguments& args) { return v8::Undefined(); } diff --git a/WebCore/bindings/v8/custom/V8LocationCustom.cpp b/WebCore/bindings/v8/custom/V8LocationCustom.cpp index 1ed4c51..ce816b6 100644 --- a/WebCore/bindings/v8/custom/V8LocationCustom.cpp +++ b/WebCore/bindings/v8/custom/V8LocationCustom.cpp @@ -29,23 +29,24 @@ */ #include "config.h" -#include "Location.h" +#include "V8Location.h" +#include "CSSHelper.h" +#include "Document.h" +#include "Frame.h" +#include "FrameLoader.h" +#include "KURL.h" +#include "Location.h" +#include "PlatformString.h" +#include "ScriptController.h" #include "V8Binding.h" +#include "V8BindingState.h" #include "V8CustomBinding.h" #include "V8CustomEventListener.h" #include "V8Location.h" #include "V8Utilities.h" #include "V8Proxy.h" -#include "PlatformString.h" -#include "KURL.h" -#include "Document.h" -#include "FrameLoader.h" -#include "ScriptController.h" -#include "CSSHelper.h" -#include "Frame.h" - namespace WebCore { // Notes about V8/JSC porting of this file. @@ -58,11 +59,11 @@ namespace WebCore { // we're just making all these custom for now. The functionality is simple // and mirrors JSLocationCustom.cpp. -ACCESSOR_SETTER(LocationHash) +void V8Location::hashAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { INC_STATS("DOM.Location.hash._set"); v8::Handle<v8::Object> holder = info.Holder(); - Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + Location* imp = V8Location::toNative(holder); String hash = toWebCoreString(value); Frame* frame = imp->frame(); @@ -81,11 +82,11 @@ ACCESSOR_SETTER(LocationHash) navigateIfAllowed(frame, url, false, false); } -ACCESSOR_SETTER(LocationHost) +void V8Location::hostAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { INC_STATS("DOM.Location.host._set"); v8::Handle<v8::Object> holder = info.Holder(); - Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + Location* imp = V8Location::toNative(holder); String host = toWebCoreString(value); Frame* frame = imp->frame(); @@ -101,11 +102,11 @@ ACCESSOR_SETTER(LocationHost) navigateIfAllowed(frame, url, false, false); } -ACCESSOR_SETTER(LocationHostname) +void V8Location::hostnameAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { INC_STATS("DOM.Location.hostname._set"); v8::Handle<v8::Object> holder = info.Holder(); - Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + Location* imp = V8Location::toNative(holder); String hostname = toWebCoreString(value); Frame* frame = imp->frame(); @@ -118,11 +119,11 @@ ACCESSOR_SETTER(LocationHostname) navigateIfAllowed(frame, url, false, false); } -ACCESSOR_SETTER(LocationHref) +void V8Location::hrefAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { INC_STATS("DOM.Location.href._set"); v8::Handle<v8::Object> holder = info.Holder(); - Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + Location* imp = V8Location::toNative(holder); Frame* frame = imp->frame(); if (!frame) @@ -138,11 +139,11 @@ ACCESSOR_SETTER(LocationHref) navigateIfAllowed(frame, url, false, false); } -ACCESSOR_SETTER(LocationPathname) +void V8Location::pathnameAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { INC_STATS("DOM.Location.pathname._set"); v8::Handle<v8::Object> holder = info.Holder(); - Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + Location* imp = V8Location::toNative(holder); String pathname = toWebCoreString(value); Frame* frame = imp->frame(); @@ -155,11 +156,11 @@ ACCESSOR_SETTER(LocationPathname) navigateIfAllowed(frame, url, false, false); } -ACCESSOR_SETTER(LocationPort) +void V8Location::portAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { INC_STATS("DOM.Location.port._set"); v8::Handle<v8::Object> holder = info.Holder(); - Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + Location* imp = V8Location::toNative(holder); String port = toWebCoreString(value); Frame* frame = imp->frame(); @@ -172,11 +173,11 @@ ACCESSOR_SETTER(LocationPort) navigateIfAllowed(frame, url, false, false); } -ACCESSOR_SETTER(LocationProtocol) +void V8Location::protocolAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { INC_STATS("DOM.Location.protocol._set"); v8::Handle<v8::Object> holder = info.Holder(); - Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + Location* imp = V8Location::toNative(holder); String protocol = toWebCoreString(value); Frame* frame = imp->frame(); @@ -189,11 +190,11 @@ ACCESSOR_SETTER(LocationProtocol) navigateIfAllowed(frame, url, false, false); } -ACCESSOR_SETTER(LocationSearch) +void V8Location::searchAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { INC_STATS("DOM.Location.search._set"); v8::Handle<v8::Object> holder = info.Holder(); - Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + Location* imp = V8Location::toNative(holder); String query = toWebCoreString(value); Frame* frame = imp->frame(); @@ -206,68 +207,68 @@ ACCESSOR_SETTER(LocationSearch) navigateIfAllowed(frame, url, false, false); } -ACCESSOR_GETTER(LocationReload) +v8::Handle<v8::Value> V8Location::reloadAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.Location.reload._get"); - static v8::Persistent<v8::FunctionTemplate> privateTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(v8LocationReloadCallback, v8::Handle<v8::Value>(), v8::Signature::New(V8Location::GetRawTemplate()))); + static v8::Persistent<v8::FunctionTemplate> privateTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(V8Location::reloadCallback, v8::Handle<v8::Value>(), v8::Signature::New(V8Location::GetRawTemplate()))); v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::LOCATION, info.This()); if (holder.IsEmpty()) { // can only reach here by 'object.__proto__.func', and it should passed // domain security check already return privateTemplate->GetFunction(); } - Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); - if (!V8Proxy::canAccessFrame(imp->frame(), false)) { - static v8::Persistent<v8::FunctionTemplate> sharedTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(v8LocationReloadCallback, v8::Handle<v8::Value>(), v8::Signature::New(V8Location::GetRawTemplate()))); + Location* imp = V8Location::toNative(holder); + if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false)) { + static v8::Persistent<v8::FunctionTemplate> sharedTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(V8Location::reloadCallback, v8::Handle<v8::Value>(), v8::Signature::New(V8Location::GetRawTemplate()))); return sharedTemplate->GetFunction(); - } else - return privateTemplate->GetFunction(); + } + return privateTemplate->GetFunction(); } -ACCESSOR_GETTER(LocationReplace) +v8::Handle<v8::Value> V8Location::replaceAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.Location.replace._get"); - static v8::Persistent<v8::FunctionTemplate> privateTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(v8LocationReplaceCallback, v8::Handle<v8::Value>(), v8::Signature::New(V8Location::GetRawTemplate()))); + static v8::Persistent<v8::FunctionTemplate> privateTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(V8Location::replaceCallback, v8::Handle<v8::Value>(), v8::Signature::New(V8Location::GetRawTemplate()))); v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::LOCATION, info.This()); if (holder.IsEmpty()) { // can only reach here by 'object.__proto__.func', and it should passed // domain security check already return privateTemplate->GetFunction(); } - Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); - if (!V8Proxy::canAccessFrame(imp->frame(), false)) { - static v8::Persistent<v8::FunctionTemplate> sharedTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(v8LocationReplaceCallback, v8::Handle<v8::Value>(), v8::Signature::New(V8Location::GetRawTemplate()))); + Location* imp = V8Location::toNative(holder); + if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false)) { + static v8::Persistent<v8::FunctionTemplate> sharedTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(V8Location::replaceCallback, v8::Handle<v8::Value>(), v8::Signature::New(V8Location::GetRawTemplate()))); return sharedTemplate->GetFunction(); - } else - return privateTemplate->GetFunction(); + } + return privateTemplate->GetFunction(); } -ACCESSOR_GETTER(LocationAssign) +v8::Handle<v8::Value> V8Location::assignAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.Location.assign._get"); static v8::Persistent<v8::FunctionTemplate> privateTemplate = - v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(v8LocationAssignCallback, v8::Handle<v8::Value>(), v8::Signature::New(V8Location::GetRawTemplate()))); + v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(V8Location::assignCallback, v8::Handle<v8::Value>(), v8::Signature::New(V8Location::GetRawTemplate()))); v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::LOCATION, info.This()); if (holder.IsEmpty()) { // can only reach here by 'object.__proto__.func', and it should passed // domain security check already return privateTemplate->GetFunction(); } - Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); - if (!V8Proxy::canAccessFrame(imp->frame(), false)) { - static v8::Persistent<v8::FunctionTemplate> sharedTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(v8LocationAssignCallback, v8::Handle<v8::Value>(), v8::Signature::New(V8Location::GetRawTemplate()))); + Location* imp = V8Location::toNative(holder); + if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false)) { + static v8::Persistent<v8::FunctionTemplate> sharedTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(V8Location::assignCallback, v8::Handle<v8::Value>(), v8::Signature::New(V8Location::GetRawTemplate()))); return sharedTemplate->GetFunction(); - } else - return privateTemplate->GetFunction(); + } + return privateTemplate->GetFunction(); } -CALLBACK_FUNC_DECL(LocationReload) +v8::Handle<v8::Value> V8Location::reloadCallback(const v8::Arguments& args) { // FIXME: we ignore the "forceget" parameter. INC_STATS("DOM.Location.reload"); v8::Handle<v8::Object> holder = args.Holder(); - Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + Location* imp = V8Location::toNative(holder); Frame* frame = imp->frame(); if (!frame || !ScriptController::isSafeScript(frame)) @@ -278,11 +279,11 @@ CALLBACK_FUNC_DECL(LocationReload) return v8::Undefined(); } -CALLBACK_FUNC_DECL(LocationReplace) +v8::Handle<v8::Value> V8Location::replaceCallback(const v8::Arguments& args) { INC_STATS("DOM.Location.replace"); v8::Handle<v8::Object> holder = args.Holder(); - Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + Location* imp = V8Location::toNative(holder); Frame* frame = imp->frame(); if (!frame) @@ -299,11 +300,11 @@ CALLBACK_FUNC_DECL(LocationReplace) return v8::Undefined(); } -CALLBACK_FUNC_DECL(LocationAssign) +v8::Handle<v8::Value> V8Location::assignCallback(const v8::Arguments& args) { INC_STATS("DOM.Location.assign"); v8::Handle<v8::Object> holder = args.Holder(); - Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + Location* imp = V8Location::toNative(holder); Frame* frame = imp->frame(); if (!frame) @@ -320,7 +321,7 @@ CALLBACK_FUNC_DECL(LocationAssign) return v8::Undefined(); } -CALLBACK_FUNC_DECL(LocationValueOf) +v8::Handle<v8::Value> V8Location::valueOfCallback(const v8::Arguments& args) { // Just return the this object the way the normal valueOf function // on the Object prototype would. The valueOf function is only @@ -330,31 +331,31 @@ CALLBACK_FUNC_DECL(LocationValueOf) return args.This(); } -CALLBACK_FUNC_DECL(LocationToString) +v8::Handle<v8::Value> V8Location::toStringCallback(const v8::Arguments& args) { INC_STATS("DOM.Location.toString"); v8::Handle<v8::Object> holder = args.Holder(); - Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); - if (!V8Proxy::canAccessFrame(imp->frame(), true)) + Location* imp = V8Location::toNative(holder); + if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true)) return v8::Undefined(); String result = imp->href(); return v8String(result); } -INDEXED_ACCESS_CHECK(Location) +bool V8Location::indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType type, v8::Local<v8::Value> data) { ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::LOCATION); // Only allow same origin access - Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, host); - return V8Proxy::canAccessFrame(imp->frame(), false); + Location* imp = V8Location::toNative(host); + return V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false); } -NAMED_ACCESS_CHECK(Location) +bool V8Location::namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value> data) { ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::LOCATION); // Only allow same origin access - Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, host); - return V8Proxy::canAccessFrame(imp->frame(), false); + Location* imp = V8Location::toNative(host); + return V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8MessageChannelConstructor.cpp b/WebCore/bindings/v8/custom/V8MessageChannelConstructor.cpp index ca02b16..3ea8e26 100644 --- a/WebCore/bindings/v8/custom/V8MessageChannelConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8MessageChannelConstructor.cpp @@ -29,13 +29,13 @@ */ #include "config.h" -#include "MessageChannel.h" - -#include "V8Binding.h" -#include "V8Proxy.h" +#include "V8MessageChannel.h" #include "Document.h" #include "Frame.h" +#include "MessageChannel.h" +#include "V8Binding.h" +#include "V8Proxy.h" #include "V8Utilities.h" #include "WorkerContext.h" #include "WorkerContextExecutionProxy.h" @@ -44,7 +44,7 @@ namespace WebCore { -CALLBACK_FUNC_DECL(MessageChannelConstructor) +v8::Handle<v8::Value> V8MessageChannel::constructorCallback(const v8::Arguments& args) { INC_STATS("DOM.MessageChannel.Constructor"); // FIXME: The logic here is almost exact duplicate of V8::constructDOMObject. @@ -66,8 +66,8 @@ CALLBACK_FUNC_DECL(MessageChannelConstructor) // 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(kMessageChannelPort1Index, V8DOMWrapper::convertToV8Object(V8ClassIndex::MESSAGEPORT, obj->port1())); - messageChannel->SetInternalField(kMessageChannelPort2Index, V8DOMWrapper::convertToV8Object(V8ClassIndex::MESSAGEPORT, obj->port2())); + messageChannel->SetInternalField(V8MessageChannel::port1Index, V8DOMWrapper::convertToV8Object(V8ClassIndex::MESSAGEPORT, obj->port1())); + messageChannel->SetInternalField(V8MessageChannel::port2Index, V8DOMWrapper::convertToV8Object(V8ClassIndex::MESSAGEPORT, obj->port2())); // Setup the standard wrapper object internal fields. V8DOMWrapper::setDOMWrapper(messageChannel, V8ClassIndex::MESSAGECHANNEL, obj.get()); diff --git a/WebCore/bindings/v8/custom/V8MessageEventCustom.cpp b/WebCore/bindings/v8/custom/V8MessageEventCustom.cpp index c5af635..9e40855 100644 --- a/WebCore/bindings/v8/custom/V8MessageEventCustom.cpp +++ b/WebCore/bindings/v8/custom/V8MessageEventCustom.cpp @@ -29,6 +29,8 @@ */ #include "config.h" +#include "V8MessageEvent.h" + #include "MessageEvent.h" #include "SerializedScriptValue.h" @@ -40,10 +42,10 @@ namespace WebCore { -ACCESSOR_GETTER(MessageEventPorts) +v8::Handle<v8::Value> V8MessageEvent::portsAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.MessageEvent.ports"); - MessageEvent* event = V8DOMWrapper::convertToNativeObject<MessageEvent>(V8ClassIndex::MESSAGEEVENT, info.Holder()); + MessageEvent* event = V8MessageEvent::toNative(info.Holder()); MessagePortArray* ports = event->ports(); if (!ports || ports->isEmpty()) @@ -56,17 +58,24 @@ ACCESSOR_GETTER(MessageEventPorts) return portArray; } -CALLBACK_FUNC_DECL(MessageEventInitMessageEvent) +v8::Handle<v8::Value> V8MessageEvent::initMessageEventCallback(const v8::Arguments& args) { INC_STATS("DOM.MessageEvent.initMessageEvent"); - MessageEvent* event = V8DOMWrapper::convertToNativeObject<MessageEvent>(V8ClassIndex::MESSAGEEVENT, args.Holder()); + MessageEvent* event = V8MessageEvent::toNative(args.Holder()); String typeArg = v8ValueToWebCoreString(args[0]); bool canBubbleArg = args[1]->BooleanValue(); bool cancelableArg = args[2]->BooleanValue(); - RefPtr<SerializedScriptValue> dataArg = SerializedScriptValue::create(v8ValueToWebCoreString(args[3])); + RefPtr<SerializedScriptValue> dataArg = SerializedScriptValue::create(args[3]); String originArg = v8ValueToWebCoreString(args[4]); String lastEventIdArg = v8ValueToWebCoreString(args[5]); - DOMWindow* sourceArg = V8DOMWindow::HasInstance(args[6]) ? V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, v8::Handle<v8::Object>::Cast(args[6])) : 0; + + DOMWindow* sourceArg = 0; + if (args[6]->IsObject()) { + v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(args[6]); + v8::Handle<v8::Object> window = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, wrapper); + if (!window.IsEmpty()) + sourceArg = V8DOMWindow::toNative(window); + } OwnPtr<MessagePortArray> portArray; if (!isUndefinedOrNull(args[7])) { diff --git a/WebCore/bindings/v8/custom/V8MessagePortCustom.cpp b/WebCore/bindings/v8/custom/V8MessagePortCustom.cpp index 0d8631f..cc70bc5 100644 --- a/WebCore/bindings/v8/custom/V8MessagePortCustom.cpp +++ b/WebCore/bindings/v8/custom/V8MessagePortCustom.cpp @@ -43,42 +43,42 @@ namespace WebCore { -CALLBACK_FUNC_DECL(MessagePortAddEventListener) +v8::Handle<v8::Value> V8MessagePort::addEventListenerCallback(const v8::Arguments& args) { INC_STATS("DOM.MessagePort.addEventListener()"); - MessagePort* messagePort = V8DOMWrapper::convertToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, args.Holder()); + 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], V8Custom::kMessagePortRequestCacheIndex); + createHiddenDependency(args.Holder(), args[1], cacheIndex); } return v8::Undefined(); } -CALLBACK_FUNC_DECL(MessagePortRemoveEventListener) +v8::Handle<v8::Value> V8MessagePort::removeEventListenerCallback(const v8::Arguments& args) { INC_STATS("DOM.MessagePort.removeEventListener()"); - MessagePort* messagePort = V8DOMWrapper::convertToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, args.Holder()); + 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], V8Custom::kMessagePortRequestCacheIndex); + removeHiddenDependency(args.Holder(), args[1], cacheIndex); } return v8::Undefined(); } -CALLBACK_FUNC_DECL(MessagePortPostMessage) +v8::Handle<v8::Value> V8MessagePort::postMessageCallback(const v8::Arguments& args) { INC_STATS("DOM.MessagePort.postMessage"); - MessagePort* messagePort = V8DOMWrapper::convertToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, args.Holder()); - RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(toWebCoreString(args[0])); + MessagePort* messagePort = V8MessagePort::toNative(args.Holder()); + RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(args[0]); MessagePortArray portArray; if (args.Length() > 1) { if (!getMessagePortArray(args[1], portArray)) @@ -129,7 +129,7 @@ bool getMessagePortArray(v8::Local<v8::Value> value, MessagePortArray& portArray throwError("MessagePortArray argument must contain only MessagePorts"); return false; } - portArray[i] = V8DOMWrapper::convertToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, v8::Handle<v8::Object>::Cast(port)); + portArray[i] = V8MessagePort::toNative(v8::Handle<v8::Object>::Cast(port)); } return true; } diff --git a/WebCore/bindings/v8/custom/V8NamedNodeMapCustom.cpp b/WebCore/bindings/v8/custom/V8NamedNodeMapCustom.cpp index afa90b7..c7fff5a 100644 --- a/WebCore/bindings/v8/custom/V8NamedNodeMapCustom.cpp +++ b/WebCore/bindings/v8/custom/V8NamedNodeMapCustom.cpp @@ -29,8 +29,9 @@ */ #include "config.h" -#include "NamedNodeMap.h" +#include "V8NamedNodeMap.h" +#include "NamedNodeMap.h" #include "V8Binding.h" #include "V8CustomBinding.h" #include "V8Proxy.h" @@ -39,10 +40,10 @@ namespace WebCore { -INDEXED_PROPERTY_GETTER(NamedNodeMap) +v8::Handle<v8::Value> V8NamedNodeMap::indexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info) { INC_STATS("DOM.NamedNodeMap.IndexedPropertyGetter"); - NamedNodeMap* imp = V8DOMWrapper::convertToNativeObject<NamedNodeMap>(V8ClassIndex::NAMEDNODEMAP, info.Holder()); + NamedNodeMap* imp = V8NamedNodeMap::toNative(info.Holder()); RefPtr<Node> result = imp->item(index); if (!result) return notHandledByInterceptor(); @@ -50,7 +51,7 @@ INDEXED_PROPERTY_GETTER(NamedNodeMap) return V8DOMWrapper::convertNodeToV8Object(result.release()); } -NAMED_PROPERTY_GETTER(NamedNodeMap) +v8::Handle<v8::Value> V8NamedNodeMap::namedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.NamedNodeMap.NamedPropertyGetter"); // Search the prototype chain first. @@ -63,7 +64,7 @@ NAMED_PROPERTY_GETTER(NamedNodeMap) return notHandledByInterceptor(); // Finally, search the DOM. - NamedNodeMap* imp = V8DOMWrapper::convertToNativeObject<NamedNodeMap>(V8ClassIndex::NAMEDNODEMAP, info.Holder()); + NamedNodeMap* imp = V8NamedNodeMap::toNative(info.Holder()); RefPtr<Node> result = imp->getNamedItem(toWebCoreString(name)); if (!result) return notHandledByInterceptor(); diff --git a/WebCore/bindings/v8/custom/V8NavigatorCustom.cpp b/WebCore/bindings/v8/custom/V8NavigatorCustom.cpp index 6a7b209..266745d 100644 --- a/WebCore/bindings/v8/custom/V8NavigatorCustom.cpp +++ b/WebCore/bindings/v8/custom/V8NavigatorCustom.cpp @@ -1,10 +1,10 @@ /* - * Copyright (C) 2007-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 * 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 @@ -29,20 +29,17 @@ */ #include "config.h" -#include "Navigator.h" +#include "V8Navigator.h" -#include "V8Binding.h" -#include "V8CustomBinding.h" -#include "V8Proxy.h" +#include "RuntimeEnabledFeatures.h" namespace WebCore { -ACCESSOR_GETTER(NavigatorAppVersion) +#if ENABLE(GEOLOCATION) +bool V8Navigator::GeolocationEnabled() { - INC_STATS("DOM.Navigator.appVersion"); - v8::Handle<v8::Object> holder = info.Holder(); - Navigator* navigator = V8DOMWrapper::convertToNativeObject<Navigator>(V8ClassIndex::NAVIGATOR, holder); - return v8StringOrUndefined(navigator->appVersion()); + return RuntimeEnabledFeatures::geolocationEnabled(); } +#endif } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8NodeCustom.cpp b/WebCore/bindings/v8/custom/V8NodeCustom.cpp index 9b4b9aa..79afbe8 100644 --- a/WebCore/bindings/v8/custom/V8NodeCustom.cpp +++ b/WebCore/bindings/v8/custom/V8NodeCustom.cpp @@ -45,25 +45,25 @@ namespace WebCore { -CALLBACK_FUNC_DECL(NodeAddEventListener) +v8::Handle<v8::Value> V8Node::addEventListenerCallback(const v8::Arguments& args) { INC_STATS("DOM.Node.addEventListener()"); - Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(args.Holder()); + 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], V8Custom::kNodeEventListenerCacheIndex); + createHiddenDependency(args.Holder(), args[1], cacheIndex); } return v8::Undefined(); } -CALLBACK_FUNC_DECL(NodeRemoveEventListener) +v8::Handle<v8::Value> V8Node::removeEventListenerCallback(const v8::Arguments& args) { INC_STATS("DOM.Node.removeEventListener()"); - Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(args.Holder()); + Node* node = V8Node::toNative(args.Holder()); // It is possbile that the owner document of the node is detached // from the frame. @@ -73,21 +73,21 @@ CALLBACK_FUNC_DECL(NodeRemoveEventListener) AtomicString type = v8ValueToAtomicWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); node->removeEventListener(type, listener.get(), useCapture); - removeHiddenDependency(args.Holder(), args[1], V8Custom::kNodeEventListenerCacheIndex); + removeHiddenDependency(args.Holder(), args[1], cacheIndex); } return v8::Undefined(); } // This function is customized to take advantage of the optional 4th argument: shouldLazyAttach -CALLBACK_FUNC_DECL(NodeInsertBefore) +v8::Handle<v8::Value> V8Node::insertBeforeCallback(const v8::Arguments& args) { INC_STATS("DOM.Node.insertBefore"); v8::Handle<v8::Object> holder = args.Holder(); - Node* imp = V8DOMWrapper::convertDOMWrapperToNode<Node>(holder); + Node* imp = V8Node::toNative(holder); ExceptionCode ec = 0; - Node* newChild = V8Node::HasInstance(args[0]) ? V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])) : 0; - Node* refChild = V8Node::HasInstance(args[1]) ? V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[1])) : 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; bool success = imp->insertBefore(newChild, refChild, ec, true); if (ec) { V8Proxy::setDOMException(ec); @@ -99,14 +99,14 @@ CALLBACK_FUNC_DECL(NodeInsertBefore) } // This function is customized to take advantage of the optional 4th argument: shouldLazyAttach -CALLBACK_FUNC_DECL(NodeReplaceChild) +v8::Handle<v8::Value> V8Node::replaceChildCallback(const v8::Arguments& args) { INC_STATS("DOM.Node.replaceChild"); v8::Handle<v8::Object> holder = args.Holder(); - Node* imp = V8DOMWrapper::convertDOMWrapperToNode<Node>(holder); + Node* imp = V8Node::toNative(holder); ExceptionCode ec = 0; - Node* newChild = V8Node::HasInstance(args[0]) ? V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])) : 0; - Node* oldChild = V8Node::HasInstance(args[1]) ? V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[1])) : 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; bool success = imp->replaceChild(newChild, oldChild, ec, true); if (ec) { V8Proxy::setDOMException(ec); @@ -117,13 +117,13 @@ CALLBACK_FUNC_DECL(NodeReplaceChild) return v8::Null(); } -CALLBACK_FUNC_DECL(NodeRemoveChild) +v8::Handle<v8::Value> V8Node::removeChildCallback(const v8::Arguments& args) { INC_STATS("DOM.Node.removeChild"); v8::Handle<v8::Object> holder = args.Holder(); - Node* imp = V8DOMWrapper::convertDOMWrapperToNode<Node>(holder); + Node* imp = V8Node::toNative(holder); ExceptionCode ec = 0; - Node* oldChild = V8Node::HasInstance(args[0]) ? V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])) : 0; + Node* oldChild = V8Node::HasInstance(args[0]) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; bool success = imp->removeChild(oldChild, ec); if (ec) { V8Proxy::setDOMException(ec); @@ -135,13 +135,13 @@ CALLBACK_FUNC_DECL(NodeRemoveChild) } // This function is customized to take advantage of the optional 4th argument: shouldLazyAttach -CALLBACK_FUNC_DECL(NodeAppendChild) +v8::Handle<v8::Value> V8Node::appendChildCallback(const v8::Arguments& args) { INC_STATS("DOM.Node.appendChild"); v8::Handle<v8::Object> holder = args.Holder(); - Node* imp = V8DOMWrapper::convertDOMWrapperToNode<Node>(holder); + Node* imp = V8Node::toNative(holder); ExceptionCode ec = 0; - Node* newChild = V8Node::HasInstance(args[0]) ? V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])) : 0; + Node* newChild = V8Node::HasInstance(args[0]) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; bool success = imp->appendChild(newChild, ec, true ); if (ec) { V8Proxy::setDOMException(ec); diff --git a/WebCore/bindings/v8/custom/V8NodeFilterCustom.cpp b/WebCore/bindings/v8/custom/V8NodeFilterCustom.cpp index 8839420..032900c 100644 --- a/WebCore/bindings/v8/custom/V8NodeFilterCustom.cpp +++ b/WebCore/bindings/v8/custom/V8NodeFilterCustom.cpp @@ -29,9 +29,10 @@ */ #include "config.h" -#include "NodeFilter.h" +#include "V8NodeFilter.h" #include "ExceptionCode.h" +#include "NodeFilter.h" #include "V8Binding.h" #include "V8CustomBinding.h" @@ -39,7 +40,7 @@ namespace WebCore { -CALLBACK_FUNC_DECL(NodeFilterAcceptNode) +v8::Handle<v8::Value> V8NodeFilter::acceptNodeCallback(const v8::Arguments& args) { INC_STATS("DOM.NodeFilter.acceptNode()"); return throwError(NOT_SUPPORTED_ERR); diff --git a/WebCore/bindings/v8/custom/V8NodeIteratorCustom.cpp b/WebCore/bindings/v8/custom/V8NodeIteratorCustom.cpp index 47ae8ee..074eac3 100644 --- a/WebCore/bindings/v8/custom/V8NodeIteratorCustom.cpp +++ b/WebCore/bindings/v8/custom/V8NodeIteratorCustom.cpp @@ -29,8 +29,9 @@ */ #include "config.h" -#include "NodeIterator.h" +#include "V8NodeIterator.h" +#include "NodeIterator.h" #include "ScriptState.h" #include "V8Binding.h" @@ -56,24 +57,24 @@ static inline v8::Handle<v8::Value> toV8(PassRefPtr<Node> object, ExceptionCode return V8DOMWrapper::convertNodeToV8Object(object); } -CALLBACK_FUNC_DECL(NodeIteratorNextNode) +v8::Handle<v8::Value> V8NodeIterator::nextNodeCallback(const v8::Arguments& args) { INC_STATS("DOM.NodeIterator.nextNode()"); - NodeIterator* nodeIterator = V8DOMWrapper::convertToNativeObject<NodeIterator>(V8ClassIndex::NODEITERATOR, args.Holder()); + NodeIterator* nodeIterator = V8NodeIterator::toNative(args.Holder()); ExceptionCode ec = 0; - ScriptState state; + EmptyScriptState state; RefPtr<Node> result = nodeIterator->nextNode(&state, ec); return toV8(result.release(), ec, &state); } -CALLBACK_FUNC_DECL(NodeIteratorPreviousNode) +v8::Handle<v8::Value> V8NodeIterator::previousNodeCallback(const v8::Arguments& args) { INC_STATS("DOM.NodeIterator.previousNode()"); - NodeIterator* nodeIterator = V8DOMWrapper::convertToNativeObject<NodeIterator>(V8ClassIndex::NODEITERATOR, args.Holder()); + NodeIterator* nodeIterator = V8NodeIterator::toNative(args.Holder()); ExceptionCode ec = 0; - ScriptState state; + EmptyScriptState state; RefPtr<Node> result = nodeIterator->previousNode(&state, ec); return toV8(result.release(), ec, &state); } diff --git a/WebCore/bindings/v8/custom/V8NodeListCustom.cpp b/WebCore/bindings/v8/custom/V8NodeListCustom.cpp index ad10952..5721a7e 100644 --- a/WebCore/bindings/v8/custom/V8NodeListCustom.cpp +++ b/WebCore/bindings/v8/custom/V8NodeListCustom.cpp @@ -29,6 +29,8 @@ */ #include "config.h" +#include "V8NodeList.h" + #include "NodeList.h" #include "V8Binding.h" @@ -40,10 +42,10 @@ namespace WebCore { -NAMED_PROPERTY_GETTER(NodeList) +v8::Handle<v8::Value> V8NodeList::namedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.NodeList.NamedPropertyGetter"); - NodeList* list = V8DOMWrapper::convertToNativeObject<NodeList>(V8ClassIndex::NODELIST, info.Holder()); + NodeList* list = V8NodeList::toNative(info.Holder()); String key = toWebCoreString(name); // Length property cannot be overridden. @@ -58,4 +60,22 @@ NAMED_PROPERTY_GETTER(NodeList) return V8DOMWrapper::convertNodeToV8Object(result.release()); } +// Need to support call so that list(0) works. +v8::Handle<v8::Value> V8NodeList::callAsFunctionCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.NodeList.callAsFunction()"); + if (args.Length() < 1) + return v8::Undefined(); + + NodeList* list = V8NodeList::toNative(args.Holder()); + + // The first argument must be a number. + v8::Local<v8::Uint32> index = args[0]->ToArrayIndex(); + if (index.IsEmpty()) + return v8::Undefined(); + + RefPtr<Node> result = list->item(index->Uint32Value()); + return V8DOMWrapper::convertNodeToV8Object(result.release()); +} + } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8NotificationCenterCustom.cpp b/WebCore/bindings/v8/custom/V8NotificationCenterCustom.cpp index a1f20cc..1cb4554 100644 --- a/WebCore/bindings/v8/custom/V8NotificationCenterCustom.cpp +++ b/WebCore/bindings/v8/custom/V8NotificationCenterCustom.cpp @@ -31,6 +31,7 @@ #include "config.h" #if ENABLE(NOTIFICATIONS) +#include "V8NotificationCenter.h" #include "NotImplemented.h" #include "Notification.h" @@ -39,6 +40,7 @@ #include "V8CustomBinding.h" #include "V8CustomEventListener.h" #include "V8CustomVoidCallback.h" +#include "V8Notification.h" #include "V8Proxy.h" #include "V8Utilities.h" #include "WorkerContext.h" @@ -46,42 +48,42 @@ namespace WebCore { -CALLBACK_FUNC_DECL(NotificationAddEventListener) +v8::Handle<v8::Value> V8Notification::addEventListenerCallback(const v8::Arguments& args) { INC_STATS("DOM.Notification.addEventListener()"); - Notification* notification = V8DOMWrapper::convertToNativeObject<Notification>(V8ClassIndex::NOTIFICATION, args.Holder()); + 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], V8Custom::kNotificationRequestCacheIndex); + createHiddenDependency(args.Holder(), args[1], cacheIndex); } return v8::Undefined(); } -CALLBACK_FUNC_DECL(NotificationRemoveEventListener) +v8::Handle<v8::Value> V8Notification::removeEventListenerCallback(const v8::Arguments& args) { INC_STATS("DOM.Notification.removeEventListener()"); - Notification* notification = V8DOMWrapper::convertToNativeObject<Notification>(V8ClassIndex::NOTIFICATION, args.Holder()); + 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], V8Custom::kNotificationRequestCacheIndex); + removeHiddenDependency(args.Holder(), args[1], cacheIndex); } return v8::Undefined(); } -CALLBACK_FUNC_DECL(NotificationCenterCreateHTMLNotification) +v8::Handle<v8::Value> V8NotificationCenter::createHTMLNotificationCallback(const v8::Arguments& args) { INC_STATS(L"DOM.NotificationCenter.CreateHTMLNotification()"); - NotificationCenter* notificationCenter = V8DOMWrapper::convertToNativeObject<NotificationCenter>(V8ClassIndex::NOTIFICATIONCENTER, args.Holder()); + NotificationCenter* notificationCenter = V8NotificationCenter::toNative(args.Holder()); ExceptionCode ec = 0; String url = toWebCoreString(args[0]); @@ -96,10 +98,10 @@ CALLBACK_FUNC_DECL(NotificationCenterCreateHTMLNotification) return V8DOMWrapper::convertToV8Object(V8ClassIndex::NOTIFICATION, notification.get()); } -CALLBACK_FUNC_DECL(NotificationCenterCreateNotification) +v8::Handle<v8::Value> V8NotificationCenter::createNotificationCallback(const v8::Arguments& args) { INC_STATS(L"DOM.NotificationCenter.CreateNotification()"); - NotificationCenter* notificationCenter = V8DOMWrapper::convertToNativeObject<NotificationCenter>(V8ClassIndex::NOTIFICATIONCENTER, args.Holder()); + NotificationCenter* notificationCenter = V8NotificationCenter::toNative(args.Holder()); ExceptionCode ec = 0; RefPtr<Notification> notification = notificationCenter->createNotification(toWebCoreString(args[0]), toWebCoreString(args[1]), toWebCoreString(args[2]), ec); @@ -113,10 +115,10 @@ CALLBACK_FUNC_DECL(NotificationCenterCreateNotification) return V8DOMWrapper::convertToV8Object(V8ClassIndex::NOTIFICATION, notification.get()); } -CALLBACK_FUNC_DECL(NotificationCenterRequestPermission) +v8::Handle<v8::Value> V8NotificationCenter::requestPermissionCallback(const v8::Arguments& args) { INC_STATS(L"DOM.NotificationCenter.RequestPermission()"); - NotificationCenter* notificationCenter = V8DOMWrapper::convertToNativeObject<NotificationCenter>(V8ClassIndex::NOTIFICATIONCENTER, args.Holder()); + NotificationCenter* notificationCenter = V8NotificationCenter::toNative(args.Holder()); ScriptExecutionContext* context = notificationCenter->context(); // Requesting permission is only valid from a page context. diff --git a/WebCore/bindings/v8/custom/V8PopStateEventCustom.cpp b/WebCore/bindings/v8/custom/V8PopStateEventCustom.cpp new file mode 100644 index 0000000..46e9929 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8PopStateEventCustom.cpp @@ -0,0 +1,67 @@ +/* + * 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 "V8PopStateEvent.h" + +#include "PopStateEvent.h" +#include "SerializedScriptValue.h" +#include "V8Proxy.h" + +namespace WebCore { + +v8::Handle<v8::Value> V8PopStateEvent::initPopStateEventCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.PopStateEvent.initPopStateEvent"); + + String typeArg = v8ValueToWebCoreString(args[0]); + bool canBubbleArg = args[1]->BooleanValue(); + bool cancelableArg = args[2]->BooleanValue(); + RefPtr<SerializedScriptValue> stateArg = SerializedScriptValue::create(args[3]); + + PopStateEvent* event = V8PopStateEvent::toNative(args.Holder()); + event->initPopStateEvent(typeArg, canBubbleArg, cancelableArg, stateArg.release()); + + return v8::Undefined(); +} + +v8::Handle<v8::Value> V8PopStateEvent::stateAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.PopStateEvent.state"); + + PopStateEvent* event = V8PopStateEvent::toNative(info.Holder()); + SerializedScriptValue* state = event->state(); + if (!state) + return v8::Null(); + + return state->deserialize(); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8SQLResultSetRowListCustom.cpp b/WebCore/bindings/v8/custom/V8SQLResultSetRowListCustom.cpp index 73aae12..ab58d1c 100644 --- a/WebCore/bindings/v8/custom/V8SQLResultSetRowListCustom.cpp +++ b/WebCore/bindings/v8/custom/V8SQLResultSetRowListCustom.cpp @@ -31,6 +31,7 @@ #include "config.h" #if ENABLE(DATABASE) +#include "V8SQLResultSetRowList.h" #include "SQLResultSetRowList.h" #include "V8Binding.h" @@ -39,7 +40,7 @@ namespace WebCore { -CALLBACK_FUNC_DECL(SQLResultSetRowListItem) +v8::Handle<v8::Value> V8SQLResultSetRowList::itemCallback(const v8::Arguments& args) { INC_STATS("DOM.SQLResultSetRowList.item()"); @@ -53,7 +54,7 @@ CALLBACK_FUNC_DECL(SQLResultSetRowListItem) return v8::Undefined(); } - SQLResultSetRowList* rowList = V8DOMWrapper::convertToNativeObject<SQLResultSetRowList>(V8ClassIndex::SQLRESULTSETROWLIST, args.Holder()); + SQLResultSetRowList* rowList = V8SQLResultSetRowList::toNative(args.Holder()); unsigned long index = args[0]->IntegerValue(); if (index < 0 || index >= rowList->length()) { diff --git a/WebCore/bindings/v8/custom/V8SQLTransactionCustom.cpp b/WebCore/bindings/v8/custom/V8SQLTransactionCustom.cpp index dc801bd..98fbd9a 100644 --- a/WebCore/bindings/v8/custom/V8SQLTransactionCustom.cpp +++ b/WebCore/bindings/v8/custom/V8SQLTransactionCustom.cpp @@ -32,6 +32,8 @@ #if ENABLE(DATABASE) +#include "V8SQLTransaction.h" + #include "Database.h" #include "SQLValue.h" #include "V8Binding.h" @@ -45,7 +47,7 @@ using namespace WTF; namespace WebCore { -CALLBACK_FUNC_DECL(SQLTransactionExecuteSql) +v8::Handle<v8::Value> V8SQLTransaction::executeSqlCallback(const v8::Arguments& args) { INC_STATS("DOM.SQLTransaction.executeSql()"); @@ -94,7 +96,7 @@ CALLBACK_FUNC_DECL(SQLTransactionExecuteSql) return throwError("sqlArgs should be array or object!", V8Proxy::TypeError); } - SQLTransaction* transaction = V8DOMWrapper::convertToNativeObject<SQLTransaction>(V8ClassIndex::SQLTRANSACTION, args.Holder()); + SQLTransaction* transaction = V8SQLTransaction::toNative(args.Holder()); Frame* frame = V8Proxy::retrieveFrameForCurrentContext(); diff --git a/WebCore/bindings/v8/custom/V8SVGElementInstanceCustom.cpp b/WebCore/bindings/v8/custom/V8SVGElementInstanceCustom.cpp index dff4ff4..23b5b06 100644 --- a/WebCore/bindings/v8/custom/V8SVGElementInstanceCustom.cpp +++ b/WebCore/bindings/v8/custom/V8SVGElementInstanceCustom.cpp @@ -31,10 +31,10 @@ #include <config.h> #if ENABLE(SVG) - -#include "SVGElementInstance.h" +#include "V8SVGElementInstance.h" #include "EventListener.h" +#include "SVGElementInstance.h" #include "V8Binding.h" #include "V8CustomBinding.h" @@ -44,33 +44,33 @@ namespace WebCore { -CALLBACK_FUNC_DECL(SVGElementInstanceAddEventListener) +v8::Handle<v8::Value> V8SVGElementInstance::addEventListenerCallback(const v8::Arguments& args) { INC_STATS("DOM.SVGElementInstance.AddEventListener()"); - SVGElementInstance* instance = V8DOMWrapper::convertDOMWrapperToNative<SVGElementInstance>(args.Holder()); + 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], V8Custom::kNodeEventListenerCacheIndex); + createHiddenDependency(args.Holder(), args[1], cacheIndex); } return v8::Undefined(); } -CALLBACK_FUNC_DECL(SVGElementInstanceRemoveEventListener) +v8::Handle<v8::Value> V8SVGElementInstance::removeEventListenerCallback(const v8::Arguments& args) { INC_STATS("DOM.SVGElementInstance.RemoveEventListener()"); - SVGElementInstance* instance = V8DOMWrapper::convertDOMWrapperToNative<SVGElementInstance>(args.Holder()); + 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], V8Custom::kNodeEventListenerCacheIndex); + removeHiddenDependency(args.Holder(), args[1], cacheIndex); } return v8::Undefined(); diff --git a/WebCore/bindings/v8/custom/V8SVGLengthCustom.cpp b/WebCore/bindings/v8/custom/V8SVGLengthCustom.cpp index 9f75f5a..129801d 100644 --- a/WebCore/bindings/v8/custom/V8SVGLengthCustom.cpp +++ b/WebCore/bindings/v8/custom/V8SVGLengthCustom.cpp @@ -31,9 +31,9 @@ #include <config.h> #if ENABLE(SVG) +#include "V8SVGLength.h" #include "SVGLength.h" - #include "V8Binding.h" #include "V8CustomBinding.h" #include "V8SVGPODTypeWrapper.h" @@ -41,18 +41,18 @@ namespace WebCore { -ACCESSOR_GETTER(SVGLengthValue) +v8::Handle<v8::Value> V8SVGLength::valueAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.SVGLength.value"); - V8SVGPODTypeWrapper<SVGLength>* wrapper = V8DOMWrapper::convertToNativeObject<V8SVGPODTypeWrapper<SVGLength> >(V8ClassIndex::SVGLENGTH, info.Holder()); + V8SVGPODTypeWrapper<SVGLength>* wrapper = V8SVGPODTypeWrapper<SVGLength>::toNative(info.Holder()); SVGLength imp = *wrapper; return v8::Number::New(imp.value(V8Proxy::svgContext(wrapper))); } -CALLBACK_FUNC_DECL(SVGLengthConvertToSpecifiedUnits) +v8::Handle<v8::Value> V8SVGLength::convertToSpecifiedUnitsCallback(const v8::Arguments& args) { INC_STATS("DOM.SVGLength.convertToSpecifiedUnits"); - V8SVGPODTypeWrapper<SVGLength>* wrapper = V8DOMWrapper::convertToNativeObject<V8SVGPODTypeWrapper<SVGLength> >(V8ClassIndex::SVGLENGTH, args.Holder()); + V8SVGPODTypeWrapper<SVGLength>* wrapper = V8SVGPODTypeWrapper<SVGLength>::toNative(args.Holder()); SVGLength imp = *wrapper; SVGElement* context = V8Proxy::svgContext(wrapper); imp.convertToSpecifiedUnits(toInt32(args[0]), context); diff --git a/WebCore/bindings/v8/custom/V8SVGMatrixCustom.cpp b/WebCore/bindings/v8/custom/V8SVGMatrixCustom.cpp index 690eac1..78284cd 100644 --- a/WebCore/bindings/v8/custom/V8SVGMatrixCustom.cpp +++ b/WebCore/bindings/v8/custom/V8SVGMatrixCustom.cpp @@ -44,7 +44,7 @@ namespace WebCore { -CALLBACK_FUNC_DECL(SVGMatrixMultiply) +v8::Handle<v8::Value> V8SVGMatrix::multiplyCallback(const v8::Arguments& args) { INC_STATS("DOM.SVGMatrix.multiply()"); if (args.Length() < 1) @@ -53,16 +53,16 @@ CALLBACK_FUNC_DECL(SVGMatrixMultiply) if (!V8SVGMatrix::HasInstance(args[0])) return throwError("secondMatrix argument was not a SVGMatrix"); - TransformationMatrix m1 = *V8DOMWrapper::convertToNativeObject<V8SVGPODTypeWrapper<TransformationMatrix> >(V8ClassIndex::SVGMATRIX, args.Holder()); - TransformationMatrix m2 = *V8DOMWrapper::convertToNativeObject<V8SVGPODTypeWrapper<TransformationMatrix> >(V8ClassIndex::SVGMATRIX, v8::Handle<v8::Object>::Cast(args[0])); + TransformationMatrix m1 = *V8SVGPODTypeWrapper<TransformationMatrix>::toNative(args.Holder()); + TransformationMatrix m2 = *V8SVGPODTypeWrapper<TransformationMatrix>::toNative(v8::Handle<v8::Object>::Cast(args[0])); return V8DOMWrapper::convertToV8Object(V8ClassIndex::SVGMATRIX, V8SVGStaticPODTypeWrapper<TransformationMatrix>::create(m1.multLeft(m2))); } -CALLBACK_FUNC_DECL(SVGMatrixInverse) +v8::Handle<v8::Value> V8SVGMatrix::inverseCallback(const v8::Arguments& args) { INC_STATS("DOM.SVGMatrix.inverse()"); - TransformationMatrix matrix = *V8DOMWrapper::convertToNativeObject<V8SVGPODTypeWrapper<TransformationMatrix> >(V8ClassIndex::SVGMATRIX, args.Holder()); + TransformationMatrix matrix = *V8SVGPODTypeWrapper<TransformationMatrix>::toNative(args.Holder()); ExceptionCode ec = 0; TransformationMatrix result = matrix.inverse(); @@ -77,10 +77,10 @@ CALLBACK_FUNC_DECL(SVGMatrixInverse) return V8DOMWrapper::convertToV8Object(V8ClassIndex::SVGMATRIX, V8SVGStaticPODTypeWrapper<TransformationMatrix>::create(result)); } -CALLBACK_FUNC_DECL(SVGMatrixRotateFromVector) +v8::Handle<v8::Value> V8SVGMatrix::rotateFromVectorCallback(const v8::Arguments& args) { INC_STATS("DOM.SVGMatrix.rotateFromVector()"); - TransformationMatrix matrix = *V8DOMWrapper::convertToNativeObject<V8SVGPODTypeWrapper<TransformationMatrix> >(V8ClassIndex::SVGMATRIX, args.Holder()); + TransformationMatrix matrix = *V8SVGPODTypeWrapper<TransformationMatrix>::toNative(args.Holder()); ExceptionCode ec = 0; float x = toFloat(args[0]); float y = toFloat(args[1]); diff --git a/WebCore/bindings/v8/custom/V8SharedWorkerCustom.cpp b/WebCore/bindings/v8/custom/V8SharedWorkerCustom.cpp index de53ac7..549de94 100644 --- a/WebCore/bindings/v8/custom/V8SharedWorkerCustom.cpp +++ b/WebCore/bindings/v8/custom/V8SharedWorkerCustom.cpp @@ -32,7 +32,7 @@ #if ENABLE(SHARED_WORKERS) -#include "SharedWorker.h" +#include "V8SharedWorker.h" #include "ExceptionCode.h" #include "Frame.h" @@ -45,7 +45,7 @@ namespace WebCore { -CALLBACK_FUNC_DECL(SharedWorkerConstructor) +v8::Handle<v8::Value> V8SharedWorker::constructorCallback(const v8::Arguments& args) { INC_STATS(L"DOM.SharedWorker.Constructor"); diff --git a/WebCore/bindings/v8/custom/V8StorageCustom.cpp b/WebCore/bindings/v8/custom/V8StorageCustom.cpp index f3f4687..ff3ac5e 100755 --- a/WebCore/bindings/v8/custom/V8StorageCustom.cpp +++ b/WebCore/bindings/v8/custom/V8StorageCustom.cpp @@ -31,6 +31,7 @@ #include "config.h" #if ENABLE(DOM_STORAGE) +#include "V8Storage.h" #include "Storage.h" #include "V8Binding.h" @@ -40,9 +41,9 @@ namespace WebCore { // Get an array containing the names of indexed properties in a collection. -v8::Handle<v8::Array> V8Custom::v8StorageNamedPropertyEnumerator(const v8::AccessorInfo& info) +v8::Handle<v8::Array> V8Storage::namedPropertyEnumerator(const v8::AccessorInfo& info) { - Storage* storage = V8DOMWrapper::convertToNativeObject<Storage>(V8ClassIndex::STORAGE, info.Holder()); + Storage* storage = V8Storage::toNative(info.Holder()); unsigned int length = storage->length(); v8::Handle<v8::Array> properties = v8::Array::New(length); for (unsigned int i = 0; i < length; ++i) { @@ -57,7 +58,7 @@ v8::Handle<v8::Array> V8Custom::v8StorageNamedPropertyEnumerator(const v8::Acces static v8::Handle<v8::Value> storageGetter(v8::Local<v8::String> v8Name, const v8::AccessorInfo& info) { - Storage* storage = V8DOMWrapper::convertToNativeObject<Storage>(V8ClassIndex::STORAGE, info.Holder()); + Storage* storage = V8Storage::toNative(info.Holder()); String name = toWebCoreString(v8Name); if (storage->contains(name) && name != "length") @@ -66,14 +67,14 @@ static v8::Handle<v8::Value> storageGetter(v8::Local<v8::String> v8Name, const v return notHandledByInterceptor(); } -INDEXED_PROPERTY_GETTER(Storage) +v8::Handle<v8::Value> V8Storage::indexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info) { INC_STATS("DOM.Storage.IndexedPropertyGetter"); v8::Local<v8::Integer> indexV8 = v8::Integer::New(index); return storageGetter(indexV8->ToString(), info); } -NAMED_PROPERTY_GETTER(Storage) +v8::Handle<v8::Value> V8Storage::namedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.Storage.NamedPropertyGetter"); return storageGetter(name, info); @@ -81,7 +82,7 @@ NAMED_PROPERTY_GETTER(Storage) static v8::Handle<v8::Value> storageSetter(v8::Local<v8::String> v8Name, v8::Local<v8::Value> v8Value, const v8::AccessorInfo& info) { - Storage* storage = V8DOMWrapper::convertToNativeObject<Storage>(V8ClassIndex::STORAGE, info.Holder()); + Storage* storage = V8Storage::toNative(info.Holder()); String name = toWebCoreString(v8Name); String value = toWebCoreString(v8Value); @@ -101,14 +102,14 @@ static v8::Handle<v8::Value> storageSetter(v8::Local<v8::String> v8Name, v8::Loc return v8Value; } -INDEXED_PROPERTY_SETTER(Storage) +v8::Handle<v8::Value> V8Storage::indexedPropertySetter(uint32_t index, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { INC_STATS("DOM.Storage.NamedPropertyGetter"); v8::Local<v8::Integer> indexV8 = v8::Integer::New(index); return storageSetter(indexV8->ToString(), value, info); } -NAMED_PROPERTY_SETTER(Storage) +v8::Handle<v8::Value> V8Storage::namedPropertySetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { INC_STATS("DOM.Storage.NamedPropertySetter"); return storageSetter(name, value, info); @@ -116,7 +117,7 @@ NAMED_PROPERTY_SETTER(Storage) static v8::Handle<v8::Boolean> storageDeleter(v8::Local<v8::String> v8Name, const v8::AccessorInfo& info) { - Storage* storage = V8DOMWrapper::convertToNativeObject<Storage>(V8ClassIndex::STORAGE, info.Holder()); + Storage* storage = V8Storage::toNative(info.Holder()); String name = toWebCoreString(v8Name); if (storage->contains(name)) { @@ -127,14 +128,14 @@ static v8::Handle<v8::Boolean> storageDeleter(v8::Local<v8::String> v8Name, cons return deletionNotHandledByInterceptor(); } -INDEXED_PROPERTY_DELETER(Storage) +v8::Handle<v8::Boolean> V8Storage::indexedPropertyDeleter(uint32_t index, const v8::AccessorInfo& info) { INC_STATS("DOM.Storage.IndexedPropertyDeleter"); v8::Local<v8::Integer> indexV8 = v8::Integer::New(index); return storageDeleter(indexV8->ToString(), info); } -NAMED_PROPERTY_DELETER(Storage) +v8::Handle<v8::Boolean> V8Storage::namedPropertyDeleter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.Storage.NamedPropertyDeleter"); return storageDeleter(name, info); diff --git a/WebCore/bindings/v8/custom/V8StyleSheetListCustom.cpp b/WebCore/bindings/v8/custom/V8StyleSheetListCustom.cpp index 32a48eb..a718451 100644 --- a/WebCore/bindings/v8/custom/V8StyleSheetListCustom.cpp +++ b/WebCore/bindings/v8/custom/V8StyleSheetListCustom.cpp @@ -29,16 +29,17 @@ */ #include "config.h" +#include "V8StyleSheetList.h" + #include "HTMLStyleElement.h" #include "StyleSheetList.h" - #include "V8Binding.h" #include "V8CustomBinding.h" #include "V8Proxy.h" namespace WebCore { -NAMED_PROPERTY_GETTER(StyleSheetList) +v8::Handle<v8::Value> V8StyleSheetList::namedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.StyleSheetList.NamedPropertyGetter"); @@ -46,7 +47,7 @@ NAMED_PROPERTY_GETTER(StyleSheetList) return notHandledByInterceptor(); // Search style sheet. - StyleSheetList* imp = V8DOMWrapper::convertToNativeObject<StyleSheetList>(V8ClassIndex::STYLESHEETLIST, info.Holder()); + StyleSheetList* imp = V8StyleSheetList::toNative(info.Holder()); HTMLStyleElement* item = imp->getNamedItem(toWebCoreString(name)); if (!item) return notHandledByInterceptor(); diff --git a/WebCore/bindings/v8/custom/V8TreeWalkerCustom.cpp b/WebCore/bindings/v8/custom/V8TreeWalkerCustom.cpp index 5052b7a..b848197 100644 --- a/WebCore/bindings/v8/custom/V8TreeWalkerCustom.cpp +++ b/WebCore/bindings/v8/custom/V8TreeWalkerCustom.cpp @@ -29,10 +29,11 @@ */ #include "config.h" -#include "TreeWalker.h" +#include "V8TreeWalker.h" #include "Node.h" #include "ScriptState.h" +#include "TreeWalker.h" #include "V8Binding.h" #include "V8CustomBinding.h" @@ -54,72 +55,72 @@ static inline v8::Handle<v8::Value> toV8(PassRefPtr<Node> object, ScriptState* s return V8DOMWrapper::convertNodeToV8Object(object); } -CALLBACK_FUNC_DECL(TreeWalkerParentNode) +v8::Handle<v8::Value> V8TreeWalker::parentNodeCallback(const v8::Arguments& args) { INC_STATS("DOM.TreeWalker.parentNode()"); - TreeWalker* treeWalker = V8DOMWrapper::convertToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); + TreeWalker* treeWalker = V8TreeWalker::toNative(args.Holder()); - ScriptState state; + EmptyScriptState state; RefPtr<Node> result = treeWalker->parentNode(&state); return toV8(result.release(), &state); } -CALLBACK_FUNC_DECL(TreeWalkerFirstChild) +v8::Handle<v8::Value> V8TreeWalker::firstChildCallback(const v8::Arguments& args) { INC_STATS("DOM.TreeWalker.firstChild()"); - TreeWalker* treeWalker = V8DOMWrapper::convertToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); + TreeWalker* treeWalker = V8TreeWalker::toNative(args.Holder()); - ScriptState state; + EmptyScriptState state; RefPtr<Node> result = treeWalker->firstChild(&state); return toV8(result.release(), &state); } -CALLBACK_FUNC_DECL(TreeWalkerLastChild) +v8::Handle<v8::Value> V8TreeWalker::lastChildCallback(const v8::Arguments& args) { INC_STATS("DOM.TreeWalker.lastChild()"); - TreeWalker* treeWalker = V8DOMWrapper::convertToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); + TreeWalker* treeWalker = V8TreeWalker::toNative(args.Holder()); - ScriptState state; + EmptyScriptState state; RefPtr<Node> result = treeWalker->lastChild(&state); return toV8(result.release(), &state); } -CALLBACK_FUNC_DECL(TreeWalkerNextNode) +v8::Handle<v8::Value> V8TreeWalker::nextNodeCallback(const v8::Arguments& args) { INC_STATS("DOM.TreeWalker.nextNode()"); - TreeWalker* treeWalker = V8DOMWrapper::convertToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); + TreeWalker* treeWalker = V8TreeWalker::toNative(args.Holder()); - ScriptState state; + EmptyScriptState state; RefPtr<Node> result = treeWalker->nextNode(&state); return toV8(result.release(), &state); } -CALLBACK_FUNC_DECL(TreeWalkerPreviousNode) +v8::Handle<v8::Value> V8TreeWalker::previousNodeCallback(const v8::Arguments& args) { INC_STATS("DOM.TreeWalker.previousNode()"); - TreeWalker* treeWalker = V8DOMWrapper::convertToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); + TreeWalker* treeWalker = V8TreeWalker::toNative(args.Holder()); - ScriptState state; + EmptyScriptState state; RefPtr<Node> result = treeWalker->previousNode(&state); return toV8(result.release(), &state); } -CALLBACK_FUNC_DECL(TreeWalkerNextSibling) +v8::Handle<v8::Value> V8TreeWalker::nextSiblingCallback(const v8::Arguments& args) { INC_STATS("DOM.TreeWalker.nextSibling()"); - TreeWalker* treeWalker = V8DOMWrapper::convertToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); + TreeWalker* treeWalker = V8TreeWalker::toNative(args.Holder()); - ScriptState state; + EmptyScriptState state; RefPtr<Node> result = treeWalker->nextSibling(&state); return toV8(result.release(), &state); } -CALLBACK_FUNC_DECL(TreeWalkerPreviousSibling) +v8::Handle<v8::Value> V8TreeWalker::previousSiblingCallback(const v8::Arguments& args) { INC_STATS("DOM.TreeWalker.previousSibling()"); - TreeWalker* treeWalker = V8DOMWrapper::convertToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); + TreeWalker* treeWalker = V8TreeWalker::toNative(args.Holder()); - ScriptState state; + EmptyScriptState state; RefPtr<Node> result = treeWalker->previousSibling(&state); return toV8(result.release(), &state); } diff --git a/WebCore/bindings/v8/custom/V8WebGLArrayBufferCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLArrayBufferCustom.cpp index 16a1f51..bc167c5 100644 --- a/WebCore/bindings/v8/custom/V8WebGLArrayBufferCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebGLArrayBufferCustom.cpp @@ -41,7 +41,7 @@ namespace WebCore { -CALLBACK_FUNC_DECL(WebGLArrayBufferConstructor) +v8::Handle<v8::Value> V8WebGLArrayBuffer::constructorCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLArrayBuffer.Constructor"); diff --git a/WebCore/bindings/v8/custom/V8WebGLArrayCustom.h b/WebCore/bindings/v8/custom/V8WebGLArrayCustom.h index 1a4b6a4..6a702f5 100644 --- a/WebCore/bindings/v8/custom/V8WebGLArrayCustom.h +++ b/WebCore/bindings/v8/custom/V8WebGLArrayCustom.h @@ -75,9 +75,7 @@ v8::Handle<v8::Value> constructWebGLArray(const v8::Arguments& args, if (argLen > 3) return throwError("Wrong number of arguments to new WebGL<T>Array(WebGLArrayBuffer, int, int)"); - WebGLArrayBuffer* buf = - V8DOMWrapper::convertToNativeObject<WebGLArrayBuffer>(V8ClassIndex::WEBGLARRAYBUFFER, - args[0]->ToObject()); + WebGLArrayBuffer* buf = V8WebGLArrayBuffer::toNative(args[0]->ToObject()); if (buf == NULL) return throwError("Could not convert argument 0 to a WebGLArrayBuffer"); bool ok; @@ -155,7 +153,7 @@ v8::Handle<v8::Value> getWebGLArrayElement(const v8::Arguments& args, V8Proxy::setDOMException(SYNTAX_ERR); return notHandledByInterceptor(); } - T* array = V8DOMWrapper::convertToNativeObject<T>(wrapperType, args.Holder()); + T* array = reinterpret_cast<T*>(args.Holder()->GetPointerFromInternalField(v8DOMWrapperObjectIndex)); if (index >= array->length()) return v8::Undefined(); ElementType result; @@ -174,9 +172,11 @@ v8::Handle<v8::Value> setWebGLArrayFromArray(T* webGLArray, const v8::Arguments& if (args.Length() == 2) offset = toInt32(args[1]); uint32_t length = toInt32(array->Get(v8::String::New("length"))); - for (uint32_t i = 0; i < length; i++) { - webGLArray->set(offset + i, array->Get(v8::Integer::New(i))->NumberValue()); - } + if (offset + length > webGLArray->length()) + 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()); } return v8::Undefined(); @@ -191,10 +191,10 @@ v8::Handle<v8::Value> setWebGLArray(const v8::Arguments& args, return notHandledByInterceptor(); } - CPlusPlusArrayType* array = V8DOMWrapper::convertToNativeObject<CPlusPlusArrayType>(wrapperType, args.Holder()); + CPlusPlusArrayType* array = JavaScriptWrapperArrayType::toNative(args.Holder()); if (args.Length() == 2 && args[0]->IsInt32()) { - // void set(in unsigned long index, in long value); + // void set(in unsigned long index, in {long|float} value); uint32_t index = toInt32(args[0]); array->set(index, args[1]->NumberValue()); return v8::Undefined(); @@ -202,7 +202,7 @@ v8::Handle<v8::Value> setWebGLArray(const v8::Arguments& args, if (JavaScriptWrapperArrayType::HasInstance(args[0])) { // void set(in WebGL<T>Array array, [Optional] in unsigned long offset); - CPlusPlusArrayType* src = V8DOMWrapper::convertToNativeObject<CPlusPlusArrayType>(wrapperType, args[0]->ToObject()); + CPlusPlusArrayType* src = JavaScriptWrapperArrayType::toNative(args[0]->ToObject()); uint32_t offset = 0; if (args.Length() == 2) offset = toInt32(args[1]); diff --git a/WebCore/bindings/v8/custom/V8WebGLByteArrayCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLByteArrayCustom.cpp index 5719c8a..6d52c83 100644 --- a/WebCore/bindings/v8/custom/V8WebGLByteArrayCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebGLByteArrayCustom.cpp @@ -44,48 +44,20 @@ namespace WebCore { -CALLBACK_FUNC_DECL(WebGLByteArrayConstructor) +v8::Handle<v8::Value> V8WebGLByteArray::constructorCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLByteArray.Contructor"); return constructWebGLArray<WebGLByteArray>(args, V8ClassIndex::ToInt(V8ClassIndex::WEBGLBYTEARRAY)); } -// Get the specified value from the byte buffer and return it wrapped as a JavaScript Number object to V8. Accesses outside the valid byte buffer range return "undefined". -INDEXED_PROPERTY_GETTER(WebGLByteArray) -{ - INC_STATS("DOM.WebGLByteArray.IndexedPropertyGetter"); - WebGLByteArray* byteBuffer = V8DOMWrapper::convertToNativeObject<WebGLByteArray>(V8ClassIndex::WEBGLBYTEARRAY, info.Holder()); - - if ((index < 0) || (index >= byteBuffer->length())) - return v8::Undefined(); - signed char result; - if (!byteBuffer->get(index, result)) - return v8::Undefined(); - return v8::Number::New(result); -} - -// Set the specified value in the byte buffer. Accesses outside the valid byte buffer range are silently ignored. -INDEXED_PROPERTY_SETTER(WebGLByteArray) -{ - INC_STATS("DOM.WebGLByteArray.IndexedPropertySetter"); - WebGLByteArray* array = V8DOMWrapper::convertToNativeObject<WebGLByteArray>(V8ClassIndex::WEBGLBYTEARRAY, info.Holder()); - - if ((index >= 0) && (index < array->length())) { - if (!value->IsNumber()) - return throwError("Could not convert value argument to a number"); - array->set(index, value->NumberValue()); - } - return value; -} - -CALLBACK_FUNC_DECL(WebGLByteArrayGet) +v8::Handle<v8::Value> V8WebGLByteArray::getCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLByteArray.get()"); return getWebGLArrayElement<WebGLByteArray, signed char>(args, V8ClassIndex::WEBGLBYTEARRAY); } -CALLBACK_FUNC_DECL(WebGLByteArraySet) +v8::Handle<v8::Value> V8WebGLByteArray::setCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLByteArray.set()"); return setWebGLArray<WebGLByteArray, V8WebGLByteArray>(args, V8ClassIndex::WEBGLBYTEARRAY); diff --git a/WebCore/bindings/v8/custom/V8WebGLFloatArrayCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLFloatArrayCustom.cpp index 6e56760..4d4b0e2 100644 --- a/WebCore/bindings/v8/custom/V8WebGLFloatArrayCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebGLFloatArrayCustom.cpp @@ -44,45 +44,20 @@ namespace WebCore { -CALLBACK_FUNC_DECL(WebGLFloatArrayConstructor) +v8::Handle<v8::Value> V8WebGLFloatArray::constructorCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLFloatArray.Contructor"); return constructWebGLArray<WebGLFloatArray>(args, V8ClassIndex::ToInt(V8ClassIndex::WEBGLFLOATARRAY)); } -// Get the specified value from the array and return it wrapped as a JavaScript Number object to V8. Accesses outside the valid array range return "undefined". -INDEXED_PROPERTY_GETTER(WebGLFloatArray) -{ - INC_STATS("DOM.WebGLFloatArray.IndexedPropertyGetter"); - WebGLFloatArray* array = V8DOMWrapper::convertToNativeObject<WebGLFloatArray>(V8ClassIndex::WEBGLFLOATARRAY, info.Holder()); - - if ((index < 0) || (index >= array->length())) - return v8::Undefined(); - float result; - if (!array->get(index, result)) - return v8::Undefined(); - return v8::Number::New(result); -} - -// Set the specified value in the array. Accesses outside the valid array range are silently ignored. -INDEXED_PROPERTY_SETTER(WebGLFloatArray) -{ - INC_STATS("DOM.WebGLFloatArray.IndexedPropertySetter"); - WebGLFloatArray* array = V8DOMWrapper::convertToNativeObject<WebGLFloatArray>(V8ClassIndex::WEBGLFLOATARRAY, info.Holder()); - - if ((index >= 0) && (index < array->length())) - array->set(index, value->NumberValue()); - return value; -} - -CALLBACK_FUNC_DECL(WebGLFloatArrayGet) +v8::Handle<v8::Value> V8WebGLFloatArray::getCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLFloatArray.get()"); return getWebGLArrayElement<WebGLFloatArray, float>(args, V8ClassIndex::WEBGLFLOATARRAY); } -CALLBACK_FUNC_DECL(WebGLFloatArraySet) +v8::Handle<v8::Value> V8WebGLFloatArray::setCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLFloatArray.set()"); return setWebGLArray<WebGLFloatArray, V8WebGLFloatArray>(args, V8ClassIndex::WEBGLFLOATARRAY); diff --git a/WebCore/bindings/v8/custom/V8WebGLIntArrayCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLIntArrayCustom.cpp index 1bd30b2..7dde0a0 100644 --- a/WebCore/bindings/v8/custom/V8WebGLIntArrayCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebGLIntArrayCustom.cpp @@ -44,48 +44,20 @@ namespace WebCore { -CALLBACK_FUNC_DECL(WebGLIntArrayConstructor) +v8::Handle<v8::Value> V8WebGLIntArray::constructorCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLIntArray.Contructor"); return constructWebGLArray<WebGLIntArray>(args, V8ClassIndex::ToInt(V8ClassIndex::WEBGLINTARRAY)); } -// Get the specified value from the integer array and return it wrapped as a JavaScript Number object to V8. Accesses outside the valid pixel buffer range return "undefined". -INDEXED_PROPERTY_GETTER(WebGLIntArray) -{ - INC_STATS("DOM.WebGLIntArray.IndexedPropertyGetter"); - WebGLIntArray* array = V8DOMWrapper::convertToNativeObject<WebGLIntArray>(V8ClassIndex::WEBGLINTARRAY, info.Holder()); - - if ((index < 0) || (index >= array->length())) - return v8::Undefined(); - int result; - if (!array->get(index, result)) - return v8::Undefined(); - return v8::Number::New(result); -} - -// Set the specified value in the integer array. Accesses outside the valid integer array range are silently ignored. -INDEXED_PROPERTY_SETTER(WebGLIntArray) -{ - INC_STATS("DOM.WebGLIntArray.IndexedPropertySetter"); - WebGLIntArray* array = V8DOMWrapper::convertToNativeObject<WebGLIntArray>(V8ClassIndex::WEBGLINTARRAY, info.Holder()); - - if ((index >= 0) && (index < array->length())) { - if (!value->IsNumber()) - return throwError("Could not convert value argument to a number"); - array->set(index, value->NumberValue()); - } - return value; -} - -CALLBACK_FUNC_DECL(WebGLIntArrayGet) +v8::Handle<v8::Value> V8WebGLIntArray::getCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLIntArray.get()"); return getWebGLArrayElement<WebGLIntArray, int>(args, V8ClassIndex::WEBGLINTARRAY); } -CALLBACK_FUNC_DECL(WebGLIntArraySet) +v8::Handle<v8::Value> V8WebGLIntArray::setCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLIntArray.set()"); return setWebGLArray<WebGLIntArray, V8WebGLIntArray>(args, V8ClassIndex::WEBGLINTARRAY); diff --git a/WebCore/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp index fd73a5b..19b73d4 100644 --- a/WebCore/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp @@ -32,7 +32,7 @@ #if ENABLE(3D_CANVAS) -#include "WebGLRenderingContext.h" +#include "V8WebGLRenderingContext.h" #include "ExceptionCode.h" @@ -54,7 +54,10 @@ #include "V8WebGLUnsignedShortArray.h" #include "V8HTMLCanvasElement.h" #include "V8HTMLImageElement.h" +#include "V8HTMLVideoElement.h" +#include "V8ImageData.h" #include "V8Proxy.h" +#include "WebGLRenderingContext.h" namespace WebCore { @@ -98,7 +101,7 @@ static int* jsArrayToIntArray(v8::Handle<v8::Array> array, uint32_t len) return data; } -CALLBACK_FUNC_DECL(WebGLRenderingContextBufferData) +v8::Handle<v8::Value> V8WebGLRenderingContext::bufferDataCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLRenderingContext.bufferData()"); @@ -112,8 +115,7 @@ CALLBACK_FUNC_DECL(WebGLRenderingContextBufferData) return notHandledByInterceptor(); } - WebGLRenderingContext* context = - V8DOMWrapper::convertDOMWrapperToNative<WebGLRenderingContext>(args.Holder()); + WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder()); bool ok; int target = toInt32(args[0], ok); if (!ok) { @@ -130,7 +132,7 @@ CALLBACK_FUNC_DECL(WebGLRenderingContextBufferData) ExceptionCode exceptionCode; context->bufferData(target, size, usage, exceptionCode); } else if (V8WebGLArray::HasInstance(args[1])) { - WebGLArray* array = V8DOMWrapper::convertToNativeObject<WebGLArray>(V8ClassIndex::WEBGLARRAY, args[1]->ToObject()); + WebGLArray* array = V8WebGLArray::toNative(args[1]->ToObject()); ExceptionCode exceptionCode; context->bufferData(target, array, usage, exceptionCode); } else { @@ -140,7 +142,7 @@ CALLBACK_FUNC_DECL(WebGLRenderingContextBufferData) return v8::Undefined(); } -CALLBACK_FUNC_DECL(WebGLRenderingContextBufferSubData) +v8::Handle<v8::Value> V8WebGLRenderingContext::bufferSubDataCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLRenderingContext.bufferSubData()"); @@ -151,8 +153,7 @@ CALLBACK_FUNC_DECL(WebGLRenderingContextBufferSubData) return notHandledByInterceptor(); } - WebGLRenderingContext* context = - V8DOMWrapper::convertDOMWrapperToNative<WebGLRenderingContext>(args.Holder()); + WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder()); bool ok; int target = toInt32(args[0], ok); if (!ok) { @@ -168,7 +169,7 @@ CALLBACK_FUNC_DECL(WebGLRenderingContextBufferSubData) V8Proxy::setDOMException(SYNTAX_ERR); return notHandledByInterceptor(); } - WebGLArray* array = V8DOMWrapper::convertToNativeObject<WebGLArray>(V8ClassIndex::WEBGLARRAY, args[2]->ToObject()); + WebGLArray* array = V8WebGLArray::toNative(args[2]->ToObject()); ExceptionCode exceptionCode; context->bufferSubData(target, offset, array, exceptionCode); return v8::Undefined(); @@ -225,8 +226,7 @@ static v8::Handle<v8::Value> getObjectParameter(const v8::Arguments& args, Objec } ExceptionCode ec = 0; - WebGLRenderingContext* context = - V8DOMWrapper::convertDOMWrapperToNative<WebGLRenderingContext>(args.Holder()); + WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder()); bool ok; unsigned target = toInt32(args[0], ok); if (!ok) { @@ -269,8 +269,7 @@ static WebGLUniformLocation* toWebGLUniformLocation(v8::Handle<v8::Value> value, ok = false; WebGLUniformLocation* location = 0; if (V8WebGLUniformLocation::HasInstance(value)) { - location = V8DOMWrapper::convertToNativeObject<WebGLUniformLocation>( - V8ClassIndex::WEBGLUNIFORMLOCATION, value->ToObject()); + location = V8WebGLUniformLocation::toNative(value->ToObject()); ok = true; } return location; @@ -280,13 +279,13 @@ enum WhichProgramCall { kProgramParameter, kUniform }; -CALLBACK_FUNC_DECL(WebGLRenderingContextGetBufferParameter) +v8::Handle<v8::Value> V8WebGLRenderingContext::getBufferParameterCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLRenderingContext.getBufferParameter()"); return getObjectParameter(args, kBuffer); } -CALLBACK_FUNC_DECL(WebGLRenderingContextGetFramebufferAttachmentParameter) +v8::Handle<v8::Value> V8WebGLRenderingContext::getFramebufferAttachmentParameterCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLRenderingContext.getFramebufferAttachmentParameter()"); @@ -296,8 +295,7 @@ CALLBACK_FUNC_DECL(WebGLRenderingContextGetFramebufferAttachmentParameter) } ExceptionCode ec = 0; - WebGLRenderingContext* context = - V8DOMWrapper::convertDOMWrapperToNative<WebGLRenderingContext>(args.Holder()); + WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder()); bool ok; unsigned target = toInt32(args[0], ok); if (!ok) { @@ -322,7 +320,7 @@ CALLBACK_FUNC_DECL(WebGLRenderingContextGetFramebufferAttachmentParameter) return toV8(info); } -CALLBACK_FUNC_DECL(WebGLRenderingContextGetParameter) +v8::Handle<v8::Value> V8WebGLRenderingContext::getParameterCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLRenderingContext.getParameter()"); @@ -332,8 +330,7 @@ CALLBACK_FUNC_DECL(WebGLRenderingContextGetParameter) } ExceptionCode ec = 0; - WebGLRenderingContext* context = - V8DOMWrapper::convertDOMWrapperToNative<WebGLRenderingContext>(args.Holder()); + WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder()); bool ok; unsigned pname = toInt32(args[0], ok); if (!ok) { @@ -348,7 +345,7 @@ CALLBACK_FUNC_DECL(WebGLRenderingContextGetParameter) return toV8(info); } -CALLBACK_FUNC_DECL(WebGLRenderingContextGetProgramParameter) +v8::Handle<v8::Value> V8WebGLRenderingContext::getProgramParameterCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLRenderingContext.getProgramParameter()"); @@ -358,9 +355,8 @@ CALLBACK_FUNC_DECL(WebGLRenderingContextGetProgramParameter) } ExceptionCode ec = 0; - WebGLRenderingContext* context = - V8DOMWrapper::convertDOMWrapperToNative<WebGLRenderingContext>(args.Holder()); - WebGLProgram* program = V8WebGLProgram::HasInstance(args[0]) ? v8DOMWrapperTo<WebGLProgram>(V8ClassIndex::WEBGLPROGRAM, v8::Handle<v8::Object>::Cast(args[0])) : 0; + WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder()); + WebGLProgram* program = V8WebGLProgram::HasInstance(args[0]) ? V8WebGLProgram::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; bool ok; unsigned pname = toInt32(args[1], ok); if (!ok) { @@ -375,13 +371,13 @@ CALLBACK_FUNC_DECL(WebGLRenderingContextGetProgramParameter) return toV8(info); } -CALLBACK_FUNC_DECL(WebGLRenderingContextGetRenderbufferParameter) +v8::Handle<v8::Value> V8WebGLRenderingContext::getRenderbufferParameterCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLRenderingContext.getRenderbufferParameter()"); return getObjectParameter(args, kRenderbuffer); } -CALLBACK_FUNC_DECL(WebGLRenderingContextGetShaderParameter) +v8::Handle<v8::Value> V8WebGLRenderingContext::getShaderParameterCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLRenderingContext.getShaderParameter()"); @@ -391,9 +387,8 @@ CALLBACK_FUNC_DECL(WebGLRenderingContextGetShaderParameter) } ExceptionCode ec = 0; - WebGLRenderingContext* context = - V8DOMWrapper::convertDOMWrapperToNative<WebGLRenderingContext>(args.Holder()); - WebGLShader* shader = V8WebGLShader::HasInstance(args[0]) ? v8DOMWrapperTo<WebGLShader>(V8ClassIndex::WEBGLSHADER, v8::Handle<v8::Object>::Cast(args[0])) : 0; + WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder()); + WebGLShader* shader = V8WebGLShader::HasInstance(args[0]) ? V8WebGLShader::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; bool ok; unsigned pname = toInt32(args[1], ok); if (!ok) { @@ -408,13 +403,13 @@ CALLBACK_FUNC_DECL(WebGLRenderingContextGetShaderParameter) return toV8(info); } -CALLBACK_FUNC_DECL(WebGLRenderingContextGetTexParameter) +v8::Handle<v8::Value> V8WebGLRenderingContext::getTexParameterCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLRenderingContext.getTexParameter()"); return getObjectParameter(args, kTexture); } -CALLBACK_FUNC_DECL(WebGLRenderingContextGetUniform) +v8::Handle<v8::Value> V8WebGLRenderingContext::getUniformCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLRenderingContext.getUniform()"); @@ -424,9 +419,8 @@ CALLBACK_FUNC_DECL(WebGLRenderingContextGetUniform) } ExceptionCode ec = 0; - WebGLRenderingContext* context = - V8DOMWrapper::convertDOMWrapperToNative<WebGLRenderingContext>(args.Holder()); - WebGLProgram* program = V8WebGLProgram::HasInstance(args[0]) ? v8DOMWrapperTo<WebGLProgram>(V8ClassIndex::WEBGLPROGRAM, v8::Handle<v8::Object>::Cast(args[0])) : 0; + WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder()); + WebGLProgram* program = V8WebGLProgram::HasInstance(args[0]) ? V8WebGLProgram::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; bool ok = false; WebGLUniformLocation* location = toWebGLUniformLocation(args[1], ok); @@ -443,13 +437,13 @@ CALLBACK_FUNC_DECL(WebGLRenderingContextGetUniform) return toV8(info); } -CALLBACK_FUNC_DECL(WebGLRenderingContextGetVertexAttrib) +v8::Handle<v8::Value> V8WebGLRenderingContext::getVertexAttribCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLRenderingContext.getVertexAttrib()"); return getObjectParameter(args, kVertexAttrib); } -CALLBACK_FUNC_DECL(WebGLRenderingContextTexImage2D) +v8::Handle<v8::Value> V8WebGLRenderingContext::texImage2DCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLRenderingContext.texImage2D()"); @@ -458,10 +452,14 @@ CALLBACK_FUNC_DECL(WebGLRenderingContextTexImage2D) // in GLint internalformat, // in GLsizei width, in GLsizei height, in GLint border, // in GLenum format, in GLenum type, in WebGLArray pixels); + // * void texImage2D(in GLenum target, in GLint level, in ImageData pixels, + // [Optional] in GLboolean flipY, [Optional] in GLboolean premulitplyAlpha); // * void texImage2D(in GLenum target, in GLint level, in HTMLImageElement image, // [Optional] in GLboolean flipY, [Optional] in GLboolean premultiplyAlpha); // * void texImage2D(in GLenum target, in GLint level, in HTMLCanvasElement image, // [Optional] in GLboolean flipY, [Optional] in GLboolean premultiplyAlpha); + // * void texImage2D(in GLenum target, in GLint level, in HTMLVideoElement image, + // [Optional] in GLboolean flipY, [Optional] in GLboolean premultiplyAlpha); if (args.Length() != 3 && args.Length() != 4 && args.Length() != 5 && @@ -470,8 +468,7 @@ CALLBACK_FUNC_DECL(WebGLRenderingContextTexImage2D) return notHandledByInterceptor(); } - WebGLRenderingContext* context = - V8DOMWrapper::convertDOMWrapperToNative<WebGLRenderingContext>(args.Holder()); + WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder()); bool ok; int target = toInt32(args[0], ok); if (!ok) { @@ -488,21 +485,28 @@ CALLBACK_FUNC_DECL(WebGLRenderingContextTexImage2D) if (args.Length() == 3 || args.Length() == 4 || args.Length() == 5) { - v8::Handle<v8::Value> arg = args[2]; bool flipY = false; bool premultiplyAlpha = false; if (args.Length() >= 4) flipY = args[3]->BooleanValue(); if (args.Length() >= 5) premultiplyAlpha = args[4]->BooleanValue(); + + v8::Handle<v8::Value> arg = args[2]; if (V8HTMLImageElement::HasInstance(arg)) { - HTMLImageElement* element = V8DOMWrapper::convertDOMWrapperToNode<HTMLImageElement>(v8::Handle<v8::Object>::Cast(arg)); + HTMLImageElement* element = V8HTMLImageElement::toNative(v8::Handle<v8::Object>::Cast(arg)); context->texImage2D(target, level, element, flipY, premultiplyAlpha, ec); } else if (V8HTMLCanvasElement::HasInstance(arg)) { - HTMLCanvasElement* element = V8DOMWrapper::convertDOMWrapperToNode<HTMLCanvasElement>(v8::Handle<v8::Object>::Cast(arg)); + HTMLCanvasElement* element = V8HTMLCanvasElement::toNative(v8::Handle<v8::Object>::Cast(arg)); context->texImage2D(target, level, element, flipY, premultiplyAlpha, ec); - } else { - // FIXME: support HTMLVideoElement and ImageData. + } else if(V8ImageData::HasInstance(arg)) { + ImageData* imageElement = V8ImageData::toNative(v8::Handle<v8::Object>::Cast(arg)); + context->texImage2D(target, level, imageElement, flipY, premultiplyAlpha, ec); + } else if (V8HTMLVideoElement::HasInstance(arg)) { + HTMLVideoElement* element = V8HTMLVideoElement::toNative(v8::Handle<v8::Object>::Cast(arg)); + context->texImage2D(target, level, element, flipY, premultiplyAlpha, ec); + } + else { // FIXME: consider different / better exception type. V8Proxy::setDOMException(SYNTAX_ERR); return notHandledByInterceptor(); @@ -540,10 +544,20 @@ CALLBACK_FUNC_DECL(WebGLRenderingContextTexImage2D) return notHandledByInterceptor(); } v8::Handle<v8::Value> arg = args[8]; - if (V8WebGLArray::HasInstance(arg)) { - WebGLArray* array = V8DOMWrapper::convertToNativeObject<WebGLArray>(V8ClassIndex::WEBGLARRAY, arg->ToObject()); - // FIXME: must do validation similar to JOGL's to ensure that - // the incoming array is of the appropriate length and type + if (!arg->IsObject()) + // Assume that the user is passing null for texture + context->texImage2D(target, + level, + internalformat, + width, + height, + border, + format, + type, + 0, + ec); + else if (V8WebGLArray::HasInstance(arg)) { + WebGLArray* array = V8WebGLArray::toNative(arg->ToObject()); context->texImage2D(target, level, internalformat, @@ -571,13 +585,145 @@ CALLBACK_FUNC_DECL(WebGLRenderingContextTexImage2D) return v8::Undefined(); } -CALLBACK_FUNC_DECL(WebGLRenderingContextTexSubImage2D) +v8::Handle<v8::Value> V8WebGLRenderingContext::texSubImage2DCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLRenderingContext.texSubImage2D()"); - // FIXME: implement - notImplemented(); + // Currently supported forms: + // * void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, + // in GLsizei width, in GLsizei height, + // in GLenum format, in GLenum type, in WebGLArray pixels); + // * void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, + // in ImageData pixels, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha); + // * void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, + // in HTMLImageElement image, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha); + // * void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, + // in HTMLCanvasElement canvas, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha); + // * void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, + // in HTMLVideoElement video, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha); + + if (args.Length() != 5 && + args.Length() != 6 && + args.Length() != 7 && + args.Length() != 9) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder()); + bool ok; + int target = toInt32(args[0], ok); + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + int level = toInt32(args[1], ok); + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + int xoff = toInt32(args[2], ok); + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + int yoff = toInt32(args[3], ok); + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + + ExceptionCode ec = 0; + if (args.Length() == 5 || + args.Length() == 6 || + args.Length() == 7) { + bool flipY = false; + bool premultiplyAlpha = false; + if (args.Length() >= 6) + flipY = args[5]->BooleanValue(); + if (args.Length() >= 7) + premultiplyAlpha = args[6]->BooleanValue(); + + v8::Handle<v8::Value> arg = args[4]; + if (V8HTMLImageElement::HasInstance(arg)) { + HTMLImageElement* element = V8HTMLImageElement::toNative(v8::Handle<v8::Object>::Cast(arg)); + context->texSubImage2D(target, level, xoff, yoff, element, flipY, premultiplyAlpha, ec); + } else if (V8HTMLCanvasElement::HasInstance(arg)) { + HTMLCanvasElement* element = V8HTMLCanvasElement::toNative(v8::Handle<v8::Object>::Cast(arg)); + context->texSubImage2D(target, level, xoff, yoff, element, flipY, premultiplyAlpha, ec); + } else if(V8ImageData::HasInstance(arg)) { + ImageData* imageElement = V8ImageData::toNative(v8::Handle<v8::Object>::Cast(arg)); + context->texSubImage2D(target, level, xoff, yoff, imageElement, flipY, premultiplyAlpha, ec); + } else if (V8HTMLVideoElement::HasInstance(arg)) { + HTMLVideoElement* element = V8HTMLVideoElement::toNative(v8::Handle<v8::Object>::Cast(arg)); + context->texSubImage2D(target, level, xoff, yoff, element, flipY, premultiplyAlpha, ec); + } + else { + // FIXME: consider different / better exception type. + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + // Fall through + } else if (args.Length() == 9) { + int width = toInt32(args[4], ok); + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + int height = toInt32(args[5], ok); + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + int format = toInt32(args[6], ok); + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + int type = toInt32(args[7], ok); + if (!ok) { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + v8::Handle<v8::Value> arg = args[8]; + if (!arg->IsObject()) + // Assume that the user is passing null for texture + context->texSubImage2D(target, + level, + xoff, + yoff, + width, + height, + format, + type, + 0, + ec); + else if (V8WebGLArray::HasInstance(arg)) { + WebGLArray* array = V8WebGLArray::toNative(arg->ToObject()); + context->texSubImage2D(target, + level, + xoff, + yoff, + width, + height, + format, + type, + array, + ec); + // Fall through + } else { + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + } else { + ASSERT_NOT_REACHED(); + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); + } + if (ec) { + V8Proxy::setDOMException(ec); + return v8::Handle<v8::Value>(); + } return v8::Undefined(); } @@ -634,16 +780,14 @@ static v8::Handle<v8::Value> vertexAttribAndUniformHelperf(const v8::Arguments& else location = toWebGLUniformLocation(args[0], ok); - WebGLRenderingContext* context = - V8DOMWrapper::convertDOMWrapperToNative<WebGLRenderingContext>(args.Holder()); + WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder()); if (!ok) { V8Proxy::setDOMException(SYNTAX_ERR); return notHandledByInterceptor(); } if (V8WebGLFloatArray::HasInstance(args[1])) { - WebGLFloatArray* array = - V8DOMWrapper::convertToNativeObject<WebGLFloatArray>(V8ClassIndex::WEBGLFLOATARRAY, args[1]->ToObject()); + WebGLFloatArray* array = V8WebGLFloatArray::toNative(args[1]->ToObject()); ASSERT(array != NULL); ExceptionCode ec = 0; switch (functionToCall) { @@ -710,8 +854,7 @@ static v8::Handle<v8::Value> uniformHelperi(const v8::Arguments& args, return notHandledByInterceptor(); } - WebGLRenderingContext* context = - V8DOMWrapper::convertDOMWrapperToNative<WebGLRenderingContext>(args.Holder()); + WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder()); bool ok = false; WebGLUniformLocation* location = toWebGLUniformLocation(args[0], ok); @@ -720,8 +863,7 @@ static v8::Handle<v8::Value> uniformHelperi(const v8::Arguments& args, return notHandledByInterceptor(); } if (V8WebGLIntArray::HasInstance(args[1])) { - WebGLIntArray* array = - V8DOMWrapper::convertToNativeObject<WebGLIntArray>(V8ClassIndex::WEBGLINTARRAY, args[1]->ToObject()); + WebGLIntArray* array = V8WebGLIntArray::toNative(args[1]->ToObject()); ASSERT(array != NULL); ExceptionCode ec = 0; switch (functionToCall) { @@ -763,49 +905,49 @@ static v8::Handle<v8::Value> uniformHelperi(const v8::Arguments& args, return v8::Undefined(); } -CALLBACK_FUNC_DECL(WebGLRenderingContextUniform1fv) +v8::Handle<v8::Value> V8WebGLRenderingContext::uniform1fvCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLRenderingContext.uniform1fv()"); return vertexAttribAndUniformHelperf(args, kUniform1v); } -CALLBACK_FUNC_DECL(WebGLRenderingContextUniform1iv) +v8::Handle<v8::Value> V8WebGLRenderingContext::uniform1ivCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLRenderingContext.uniform1iv()"); return uniformHelperi(args, kUniform1v); } -CALLBACK_FUNC_DECL(WebGLRenderingContextUniform2fv) +v8::Handle<v8::Value> V8WebGLRenderingContext::uniform2fvCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLRenderingContext.uniform2fv()"); return vertexAttribAndUniformHelperf(args, kUniform2v); } -CALLBACK_FUNC_DECL(WebGLRenderingContextUniform2iv) +v8::Handle<v8::Value> V8WebGLRenderingContext::uniform2ivCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLRenderingContext.uniform2iv()"); return uniformHelperi(args, kUniform2v); } -CALLBACK_FUNC_DECL(WebGLRenderingContextUniform3fv) +v8::Handle<v8::Value> V8WebGLRenderingContext::uniform3fvCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLRenderingContext.uniform3fv()"); return vertexAttribAndUniformHelperf(args, kUniform3v); } -CALLBACK_FUNC_DECL(WebGLRenderingContextUniform3iv) +v8::Handle<v8::Value> V8WebGLRenderingContext::uniform3ivCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLRenderingContext.uniform3iv()"); return uniformHelperi(args, kUniform3v); } -CALLBACK_FUNC_DECL(WebGLRenderingContextUniform4fv) +v8::Handle<v8::Value> V8WebGLRenderingContext::uniform4fvCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLRenderingContext.uniform4fv()"); return vertexAttribAndUniformHelperf(args, kUniform4v); } -CALLBACK_FUNC_DECL(WebGLRenderingContextUniform4iv) +v8::Handle<v8::Value> V8WebGLRenderingContext::uniform4ivCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLRenderingContext.uniform4iv()"); return uniformHelperi(args, kUniform4v); @@ -828,8 +970,7 @@ static v8::Handle<v8::Value> uniformMatrixHelper(const v8::Arguments& args, return notHandledByInterceptor(); } - WebGLRenderingContext* context = - V8DOMWrapper::convertDOMWrapperToNative<WebGLRenderingContext>(args.Holder()); + WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder()); bool ok = false; WebGLUniformLocation* location = toWebGLUniformLocation(args[0], ok); @@ -840,8 +981,7 @@ static v8::Handle<v8::Value> uniformMatrixHelper(const v8::Arguments& args, } bool transpose = args[1]->BooleanValue(); if (V8WebGLFloatArray::HasInstance(args[2])) { - WebGLFloatArray* array = - V8DOMWrapper::convertToNativeObject<WebGLFloatArray>(V8ClassIndex::WEBGLFLOATARRAY, args[2]->ToObject()); + WebGLFloatArray* array = V8WebGLFloatArray::toNative(args[2]->ToObject()); ASSERT(array != NULL); ExceptionCode ec = 0; switch (matrixSize) { @@ -881,43 +1021,43 @@ static v8::Handle<v8::Value> uniformMatrixHelper(const v8::Arguments& args, return v8::Undefined(); } -CALLBACK_FUNC_DECL(WebGLRenderingContextUniformMatrix2fv) +v8::Handle<v8::Value> V8WebGLRenderingContext::uniformMatrix2fvCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLRenderingContext.uniformMatrix2fv()"); return uniformMatrixHelper(args, 2); } -CALLBACK_FUNC_DECL(WebGLRenderingContextUniformMatrix3fv) +v8::Handle<v8::Value> V8WebGLRenderingContext::uniformMatrix3fvCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLRenderingContext.uniformMatrix3fv()"); return uniformMatrixHelper(args, 3); } -CALLBACK_FUNC_DECL(WebGLRenderingContextUniformMatrix4fv) +v8::Handle<v8::Value> V8WebGLRenderingContext::uniformMatrix4fvCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLRenderingContext.uniformMatrix4fv()"); return uniformMatrixHelper(args, 4); } -CALLBACK_FUNC_DECL(WebGLRenderingContextVertexAttrib1fv) +v8::Handle<v8::Value> V8WebGLRenderingContext::vertexAttrib1fvCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLRenderingContext.vertexAttrib1fv()"); return vertexAttribAndUniformHelperf(args, kVertexAttrib1v); } -CALLBACK_FUNC_DECL(WebGLRenderingContextVertexAttrib2fv) +v8::Handle<v8::Value> V8WebGLRenderingContext::vertexAttrib2fvCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLRenderingContext.vertexAttrib2fv()"); return vertexAttribAndUniformHelperf(args, kVertexAttrib2v); } -CALLBACK_FUNC_DECL(WebGLRenderingContextVertexAttrib3fv) +v8::Handle<v8::Value> V8WebGLRenderingContext::vertexAttrib3fvCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLRenderingContext.vertexAttrib3fv()"); return vertexAttribAndUniformHelperf(args, kVertexAttrib3v); } -CALLBACK_FUNC_DECL(WebGLRenderingContextVertexAttrib4fv) +v8::Handle<v8::Value> V8WebGLRenderingContext::vertexAttrib4fvCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLRenderingContext.vertexAttrib4fv()"); return vertexAttribAndUniformHelperf(args, kVertexAttrib4v); diff --git a/WebCore/bindings/v8/custom/V8WebGLShortArrayCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLShortArrayCustom.cpp index f8a26c3..9d3b478 100644 --- a/WebCore/bindings/v8/custom/V8WebGLShortArrayCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebGLShortArrayCustom.cpp @@ -44,48 +44,20 @@ namespace WebCore { -CALLBACK_FUNC_DECL(WebGLShortArrayConstructor) +v8::Handle<v8::Value> V8WebGLShortArray::constructorCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLShortArray.Contructor"); return constructWebGLArray<WebGLShortArray>(args, V8ClassIndex::ToInt(V8ClassIndex::WEBGLSHORTARRAY)); } -// Get the specified value from the array and return it wrapped as a JavaScript Number object to V8. Accesses outside the valid array range return "undefined". -INDEXED_PROPERTY_GETTER(WebGLShortArray) -{ - INC_STATS("DOM.WebGLShortArray.IndexedPropertyGetter"); - WebGLShortArray* array = V8DOMWrapper::convertToNativeObject<WebGLShortArray>(V8ClassIndex::WEBGLSHORTARRAY, info.Holder()); - - if ((index < 0) || (index >= array->length())) - return v8::Undefined(); - short result; - if (!array->get(index, result)) - return v8::Undefined(); - return v8::Number::New(result); -} - -// Set the specified value in the array. Accesses outside the valid array range are silently ignored. -INDEXED_PROPERTY_SETTER(WebGLShortArray) -{ - INC_STATS("DOM.WebGLShortArray.IndexedPropertySetter"); - WebGLShortArray* array = V8DOMWrapper::convertToNativeObject<WebGLShortArray>(V8ClassIndex::WEBGLSHORTARRAY, info.Holder()); - - if ((index >= 0) && (index < array->length())) { - if (!value->IsNumber()) - return throwError("Could not convert value argument to a number"); - array->set(index, value->NumberValue()); - } - return value; -} - -CALLBACK_FUNC_DECL(WebGLShortArrayGet) +v8::Handle<v8::Value> V8WebGLShortArray::getCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLShortArray.get()"); return getWebGLArrayElement<WebGLShortArray, short>(args, V8ClassIndex::WEBGLSHORTARRAY); } -CALLBACK_FUNC_DECL(WebGLShortArraySet) +v8::Handle<v8::Value> V8WebGLShortArray::setCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLShortArray.set()"); return setWebGLArray<WebGLShortArray, V8WebGLShortArray>(args, V8ClassIndex::WEBGLSHORTARRAY); diff --git a/WebCore/bindings/v8/custom/V8WebGLUnsignedByteArrayCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLUnsignedByteArrayCustom.cpp index 391f213..3cc658a 100644 --- a/WebCore/bindings/v8/custom/V8WebGLUnsignedByteArrayCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebGLUnsignedByteArrayCustom.cpp @@ -44,48 +44,20 @@ namespace WebCore { -CALLBACK_FUNC_DECL(WebGLUnsignedByteArrayConstructor) +v8::Handle<v8::Value> V8WebGLUnsignedByteArray::constructorCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLUnsignedByteArray.Contructor"); return constructWebGLArray<WebGLUnsignedByteArray>(args, V8ClassIndex::ToInt(V8ClassIndex::WEBGLUNSIGNEDBYTEARRAY)); } -// Get the specified value from the array and return it wrapped as a JavaScript Number object to V8. Accesses outside the valid array range return "undefined". -INDEXED_PROPERTY_GETTER(WebGLUnsignedByteArray) -{ - INC_STATS("DOM.WebGLUnsignedByteArray.IndexedPropertyGetter"); - WebGLUnsignedByteArray* array = V8DOMWrapper::convertToNativeObject<WebGLUnsignedByteArray>(V8ClassIndex::WEBGLUNSIGNEDBYTEARRAY, info.Holder()); - - if ((index < 0) || (index >= array->length())) - return v8::Undefined(); - unsigned char result; - if (!array->get(index, result)) - return v8::Undefined(); - return v8::Number::New(result); -} - -// Set the specified value in the array. Accesses outside the valid array range are silently ignored. -INDEXED_PROPERTY_SETTER(WebGLUnsignedByteArray) -{ - INC_STATS("DOM.WebGLUnsignedByteArray.IndexedPropertySetter"); - WebGLUnsignedByteArray* array = V8DOMWrapper::convertToNativeObject<WebGLUnsignedByteArray>(V8ClassIndex::WEBGLUNSIGNEDBYTEARRAY, info.Holder()); - - if ((index >= 0) && (index < array->length())) { - if (!value->IsNumber()) - return throwError("Could not convert value argument to a number"); - array->set(index, value->NumberValue()); - } - return value; -} - -CALLBACK_FUNC_DECL(WebGLUnsignedByteArrayGet) +v8::Handle<v8::Value> V8WebGLUnsignedByteArray::getCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLUnsignedByteArray.get()"); return getWebGLArrayElement<WebGLUnsignedByteArray, unsigned char>(args, V8ClassIndex::WEBGLUNSIGNEDBYTEARRAY); } -CALLBACK_FUNC_DECL(WebGLUnsignedByteArraySet) +v8::Handle<v8::Value> V8WebGLUnsignedByteArray::setCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLUnsignedByteArray.set()"); return setWebGLArray<WebGLUnsignedByteArray, V8WebGLUnsignedByteArray>(args, V8ClassIndex::WEBGLUNSIGNEDBYTEARRAY); diff --git a/WebCore/bindings/v8/custom/V8WebGLUnsignedIntArrayCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLUnsignedIntArrayCustom.cpp index 92b9fe0..93ccbd4 100644 --- a/WebCore/bindings/v8/custom/V8WebGLUnsignedIntArrayCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebGLUnsignedIntArrayCustom.cpp @@ -44,48 +44,20 @@ namespace WebCore { -CALLBACK_FUNC_DECL(WebGLUnsignedIntArrayConstructor) +v8::Handle<v8::Value> V8WebGLUnsignedIntArray::constructorCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLUnsignedIntArray.Contructor"); return constructWebGLArray<WebGLUnsignedIntArray>(args, V8ClassIndex::ToInt(V8ClassIndex::WEBGLUNSIGNEDINTARRAY)); } -// Get the specified value from the integer array and return it wrapped as a JavaScript Number object to V8. Accesses outside the valid pixel buffer range return "undefined". -INDEXED_PROPERTY_GETTER(WebGLUnsignedIntArray) -{ - INC_STATS("DOM.WebGLUnsignedIntArray.IndexedPropertyGetter"); - WebGLUnsignedIntArray* array = V8DOMWrapper::convertToNativeObject<WebGLUnsignedIntArray>(V8ClassIndex::WEBGLUNSIGNEDINTARRAY, info.Holder()); - - if ((index < 0) || (index >= array->length())) - return v8::Undefined(); - unsigned int result; - if (!array->get(index, result)) - return v8::Undefined(); - return v8::Number::New(result); -} - -// Set the specified value in the integer array. Accesses outside the valid integer array range are silently ignored. -INDEXED_PROPERTY_SETTER(WebGLUnsignedIntArray) -{ - INC_STATS("DOM.WebGLUnsignedIntArray.IndexedPropertySetter"); - WebGLUnsignedIntArray* array = V8DOMWrapper::convertToNativeObject<WebGLUnsignedIntArray>(V8ClassIndex::WEBGLUNSIGNEDINTARRAY, info.Holder()); - - if ((index >= 0) && (index < array->length())) { - if (!value->IsNumber()) - return throwError("Could not convert value argument to a number"); - array->set(index, value->NumberValue()); - } - return value; -} - -CALLBACK_FUNC_DECL(WebGLUnsignedIntArrayGet) +v8::Handle<v8::Value> V8WebGLUnsignedIntArray::getCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLUnsignedIntArray.get()"); return getWebGLArrayElement<WebGLUnsignedIntArray, unsigned int>(args, V8ClassIndex::WEBGLUNSIGNEDINTARRAY); } -CALLBACK_FUNC_DECL(WebGLUnsignedIntArraySet) +v8::Handle<v8::Value> V8WebGLUnsignedIntArray::setCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLUnsignedIntArray.set()"); return setWebGLArray<WebGLUnsignedIntArray, V8WebGLUnsignedIntArray>(args, V8ClassIndex::WEBGLUNSIGNEDINTARRAY); diff --git a/WebCore/bindings/v8/custom/V8WebGLUnsignedShortArrayCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLUnsignedShortArrayCustom.cpp index ce261e9..d9e47cd 100644 --- a/WebCore/bindings/v8/custom/V8WebGLUnsignedShortArrayCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebGLUnsignedShortArrayCustom.cpp @@ -44,48 +44,20 @@ namespace WebCore { -CALLBACK_FUNC_DECL(WebGLUnsignedShortArrayConstructor) +v8::Handle<v8::Value> V8WebGLUnsignedShortArray::constructorCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLUnsignedShortArray.Contructor"); return constructWebGLArray<WebGLUnsignedShortArray>(args, V8ClassIndex::ToInt(V8ClassIndex::WEBGLUNSIGNEDSHORTARRAY)); } -// Get the specified value from the array and return it wrapped as a JavaScript Number object to V8. Accesses outside the valid array range return "undefined". -INDEXED_PROPERTY_GETTER(WebGLUnsignedShortArray) -{ - INC_STATS("DOM.WebGLUnsignedShortArray.IndexedPropertyGetter"); - WebGLUnsignedShortArray* array = V8DOMWrapper::convertToNativeObject<WebGLUnsignedShortArray>(V8ClassIndex::WEBGLUNSIGNEDSHORTARRAY, info.Holder()); - - if ((index < 0) || (index >= array->length())) - return v8::Undefined(); - unsigned short result; - if (!array->get(index, result)) - return v8::Undefined(); - return v8::Number::New(result); -} - -// Set the specified value in the array. Accesses outside the valid array range are silently ignored. -INDEXED_PROPERTY_SETTER(WebGLUnsignedShortArray) -{ - INC_STATS("DOM.WebGLUnsignedShortArray.IndexedPropertySetter"); - WebGLUnsignedShortArray* array = V8DOMWrapper::convertToNativeObject<WebGLUnsignedShortArray>(V8ClassIndex::WEBGLUNSIGNEDSHORTARRAY, info.Holder()); - - if ((index >= 0) && (index < array->length())) { - if (!value->IsNumber()) - return throwError("Could not convert value argument to a number"); - array->set(index, value->NumberValue()); - } - return value; -} - -CALLBACK_FUNC_DECL(WebGLUnsignedShortArrayGet) +v8::Handle<v8::Value> V8WebGLUnsignedShortArray::getCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLUnsignedShortArray.get()"); return getWebGLArrayElement<WebGLUnsignedShortArray, unsigned short>(args, V8ClassIndex::WEBGLUNSIGNEDSHORTARRAY); } -CALLBACK_FUNC_DECL(WebGLUnsignedShortArraySet) +v8::Handle<v8::Value> V8WebGLUnsignedShortArray::setCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLUnsignedShortArray.set()"); return setWebGLArray<WebGLUnsignedShortArray, V8WebGLUnsignedShortArray>(args, V8ClassIndex::WEBGLUNSIGNEDSHORTARRAY); diff --git a/WebCore/bindings/v8/custom/V8WebKitCSSMatrixConstructor.cpp b/WebCore/bindings/v8/custom/V8WebKitCSSMatrixConstructor.cpp index 4819064..55518d2 100644 --- a/WebCore/bindings/v8/custom/V8WebKitCSSMatrixConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8WebKitCSSMatrixConstructor.cpp @@ -29,7 +29,7 @@ */ #include "config.h" -#include "WebKitCSSMatrix.h" +#include "V8WebKitCSSMatrix.h" #include "Document.h" #include "DocumentFragment.h" @@ -44,7 +44,7 @@ namespace WebCore { -CALLBACK_FUNC_DECL(WebKitCSSMatrixConstructor) +v8::Handle<v8::Value> V8WebKitCSSMatrix::constructorCallback(const v8::Arguments& args) { INC_STATS("DOM.WebKitCSSMatrix.Constructor"); diff --git a/WebCore/bindings/v8/custom/V8WebKitPointConstructor.cpp b/WebCore/bindings/v8/custom/V8WebKitPointConstructor.cpp index b2a807d..4e0d575 100755 --- a/WebCore/bindings/v8/custom/V8WebKitPointConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8WebKitPointConstructor.cpp @@ -29,19 +29,19 @@ */ #include "config.h" +#include "V8WebKitPoint.h" #include "V8Binding.h" #include "V8CustomBinding.h" #include "V8DOMWrapper.h" #include "V8Index.h" #include "V8Proxy.h" -#include "WebKitPoint.h" #include <wtf/MathExtras.h> namespace WebCore { -CALLBACK_FUNC_DECL(WebKitPointConstructor) +v8::Handle<v8::Value> V8WebKitPoint::constructorCallback(const v8::Arguments& args) { INC_STATS("DOM.WebKitPoint.Constructor"); float x = 0; diff --git a/WebCore/bindings/v8/custom/V8WebSocketCustom.cpp b/WebCore/bindings/v8/custom/V8WebSocketCustom.cpp index b20635b..2451b90 100644 --- a/WebCore/bindings/v8/custom/V8WebSocketCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebSocketCustom.cpp @@ -32,22 +32,23 @@ #if ENABLE(WEB_SOCKETS) -#include "WebSocket.h" +#include "V8WebSocket.h" #include "Frame.h" #include "Settings.h" #include "V8Binding.h" #include "V8Proxy.h" #include "V8Utilities.h" +#include "WebSocket.h" #include "WorkerContext.h" #include "WorkerContextExecutionProxy.h" namespace WebCore { -CALLBACK_FUNC_DECL(WebSocketAddEventListener) +v8::Handle<v8::Value> V8WebSocket::addEventListenerCallback(const v8::Arguments& args) { INC_STATS("DOM.WebSocket.addEventListener()"); - WebSocket* webSocket = V8DOMWrapper::convertToNativeObject<WebSocket>(V8ClassIndex::WEBSOCKET, args.Holder()); + WebSocket* webSocket = V8WebSocket::toNative(args.Holder()); RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(webSocket, args[1], false, ListenerFindOrCreate); if (listener) { @@ -55,27 +56,27 @@ CALLBACK_FUNC_DECL(WebSocketAddEventListener) bool useCapture = args[2]->BooleanValue(); webSocket->addEventListener(type, listener, useCapture); - createHiddenDependency(args.Holder(), args[1], V8Custom::kWebSocketCacheIndex); + createHiddenDependency(args.Holder(), args[1], cacheIndex); } return v8::Undefined(); } -CALLBACK_FUNC_DECL(WebSocketRemoveEventListener) +v8::Handle<v8::Value> V8WebSocket::removeEventListenerCallback(const v8::Arguments& args) { INC_STATS("DOM.WebSocket.removeEventListener()"); - WebSocket* webSocket = V8DOMWrapper::convertToNativeObject<WebSocket>(V8ClassIndex::WEBSOCKET, args.Holder()); + 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], V8Custom::kWebSocketCacheIndex); + removeHiddenDependency(args.Holder(), args[1], cacheIndex); } return v8::Undefined(); } -CALLBACK_FUNC_DECL(WebSocketConstructor) +v8::Handle<v8::Value> V8WebSocket::constructorCallback(const v8::Arguments& args) { INC_STATS("DOM.WebSocket.Constructor"); @@ -92,14 +93,9 @@ CALLBACK_FUNC_DECL(WebSocketConstructor) return throwError("Empty URL", V8Proxy::SyntaxError); // Get the script execution context. - ScriptExecutionContext* context = 0; - // TODO: Workers - if (!context) { - Frame* frame = V8Proxy::retrieveFrameForCurrentContext(); - if (!frame) - return throwError("WebSocket constructor's associated frame is not available", V8Proxy::ReferenceError); - context = frame->document(); - } + ScriptExecutionContext* context = getScriptExecutionContext(); + if (!context) + return throwError("WebSocket constructor's associated frame is not available", V8Proxy::ReferenceError); const KURL& url = context->completeURL(toWebCoreString(urlstring)); @@ -128,10 +124,10 @@ CALLBACK_FUNC_DECL(WebSocketConstructor) return args.Holder(); } -CALLBACK_FUNC_DECL(WebSocketSend) +v8::Handle<v8::Value> V8WebSocket::sendCallback(const v8::Arguments& args) { INC_STATS("DOM.WebSocket.send()"); - WebSocket* webSocket = V8DOMWrapper::convertToNativeObject<WebSocket>(V8ClassIndex::WEBSOCKET, args.Holder()); + WebSocket* webSocket = V8WebSocket::toNative(args.Holder()); ExceptionCode ec = 0; bool ret = false; @@ -146,15 +142,6 @@ CALLBACK_FUNC_DECL(WebSocketSend) return v8Boolean(ret); } -CALLBACK_FUNC_DECL(WebSocketClose) -{ - INC_STATS("DOM.WebSocket.close()"); - WebSocket* webSocket = V8DOMWrapper::convertToNativeObject<WebSocket>(V8ClassIndex::WEBSOCKET, args.Holder()); - - webSocket->close(); - return v8::Undefined(); -} - } // namespace WebCore #endif // ENABLE(WEB_SOCKETS) diff --git a/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp b/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp index 9b68ac0..9d54f8e 100755 --- a/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp @@ -31,6 +31,7 @@ #include "config.h" #if ENABLE(WORKERS) +#include "V8WorkerContext.h" #include "DOMTimer.h" #include "ExceptionCode.h" @@ -41,28 +42,29 @@ #include "V8Proxy.h" #include "V8Utilities.h" #include "V8WorkerContextEventListener.h" +#include "WebSocket.h" #include "WorkerContext.h" #include "WorkerContextExecutionProxy.h" namespace WebCore { #if ENABLE(NOTIFICATIONS) -ACCESSOR_RUNTIME_ENABLER(WorkerContextWebkitNotifications) +bool V8WorkerContext::WebkitNotificationsEnabled() { return RuntimeEnabledFeatures::notificationsEnabled(); } #endif -ACCESSOR_GETTER(WorkerContextSelf) +#if ENABLE(WEB_SOCKETS) +bool V8WorkerContext::WebSocketEnabled() { - INC_STATS(L"DOM.WorkerContext.self._get"); - WorkerContext* workerContext = V8DOMWrapper::convertDOMWrapperToNative<WorkerContext>(info.Holder()); - return WorkerContextExecutionProxy::convertWorkerContextToV8Object(workerContext); + return WebSocket::isAvailable(); } +#endif v8::Handle<v8::Value> SetTimeoutOrInterval(const v8::Arguments& args, bool singleShot) { - WorkerContext* workerContext = V8DOMWrapper::convertDOMWrapperToNative<WorkerContext>(args.Holder()); + WorkerContext* workerContext = V8WorkerContext::toNative(args.Holder()); int argumentCount = args.Length(); if (argumentCount < 1) @@ -94,7 +96,7 @@ v8::Handle<v8::Value> SetTimeoutOrInterval(const v8::Arguments& args, bool singl return v8::Integer::New(timerId); } -CALLBACK_FUNC_DECL(WorkerContextImportScripts) +v8::Handle<v8::Value> V8WorkerContext::importScriptsCallback(const v8::Arguments& args) { INC_STATS(L"DOM.WorkerContext.importScripts()"); if (!args.Length()) @@ -117,7 +119,7 @@ CALLBACK_FUNC_DECL(WorkerContextImportScripts) urls.append(toWebCoreString(scriptUrl)); } - WorkerContext* workerContext = V8DOMWrapper::convertDOMWrapperToNative<WorkerContext>(args.Holder()); + WorkerContext* workerContext = V8WorkerContext::toNative(args.Holder()); ExceptionCode ec = 0; workerContext->importScripts(urls, callerURL, callerLine, ec); @@ -128,22 +130,22 @@ CALLBACK_FUNC_DECL(WorkerContextImportScripts) return v8::Undefined(); } -CALLBACK_FUNC_DECL(WorkerContextSetTimeout) +v8::Handle<v8::Value> V8WorkerContext::setTimeoutCallback(const v8::Arguments& args) { INC_STATS(L"DOM.WorkerContext.setTimeout()"); return SetTimeoutOrInterval(args, true); } -CALLBACK_FUNC_DECL(WorkerContextSetInterval) +v8::Handle<v8::Value> V8WorkerContext::setIntervalCallback(const v8::Arguments& args) { INC_STATS(L"DOM.WorkerContext.setInterval()"); return SetTimeoutOrInterval(args, false); } -CALLBACK_FUNC_DECL(WorkerContextAddEventListener) +v8::Handle<v8::Value> V8WorkerContext::addEventListenerCallback(const v8::Arguments& args) { INC_STATS(L"DOM.WorkerContext.addEventListener()"); - WorkerContext* workerContext = V8DOMWrapper::convertDOMWrapperToNative<WorkerContext>(args.Holder()); + WorkerContext* workerContext = V8WorkerContext::toNative(args.Holder()); RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(workerContext, args[1], false, ListenerFindOrCreate); if (listener) { @@ -151,15 +153,15 @@ CALLBACK_FUNC_DECL(WorkerContextAddEventListener) bool useCapture = args[2]->BooleanValue(); workerContext->addEventListener(type, listener, useCapture); - createHiddenDependency(args.Holder(), args[1], V8Custom::kWorkerContextRequestCacheIndex); + createHiddenDependency(args.Holder(), args[1], cacheIndex); } return v8::Undefined(); } -CALLBACK_FUNC_DECL(WorkerContextRemoveEventListener) +v8::Handle<v8::Value> V8WorkerContext::removeEventListenerCallback(const v8::Arguments& args) { INC_STATS(L"DOM.WorkerContext.removeEventListener()"); - WorkerContext* workerContext = V8DOMWrapper::convertDOMWrapperToNative<WorkerContext>(args.Holder()); + WorkerContext* workerContext = V8WorkerContext::toNative(args.Holder()); RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(workerContext, args[1], false, ListenerFindOnly); if (listener) { @@ -167,7 +169,7 @@ CALLBACK_FUNC_DECL(WorkerContextRemoveEventListener) bool useCapture = args[2]->BooleanValue(); workerContext->removeEventListener(type, listener.get(), useCapture); - removeHiddenDependency(args.Holder(), args[1], V8Custom::kWorkerContextRequestCacheIndex); + removeHiddenDependency(args.Holder(), args[1], cacheIndex); } return v8::Undefined(); } diff --git a/WebCore/bindings/v8/custom/V8WorkerCustom.cpp b/WebCore/bindings/v8/custom/V8WorkerCustom.cpp index 454e41f..ffca2a4 100755 --- a/WebCore/bindings/v8/custom/V8WorkerCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WorkerCustom.cpp @@ -31,6 +31,7 @@ #include "config.h" #if ENABLE(WORKERS) +#include "V8Worker.h" #include "Worker.h" @@ -47,7 +48,7 @@ namespace WebCore { -CALLBACK_FUNC_DECL(WorkerConstructor) +v8::Handle<v8::Value> V8Worker::constructorCallback(const v8::Arguments& args) { INC_STATS(L"DOM.Worker.Constructor"); @@ -87,11 +88,11 @@ CALLBACK_FUNC_DECL(WorkerConstructor) return wrapperObject; } -CALLBACK_FUNC_DECL(WorkerPostMessage) +v8::Handle<v8::Value> V8Worker::postMessageCallback(const v8::Arguments& args) { INC_STATS("DOM.Worker.postMessage"); - Worker* worker = V8DOMWrapper::convertToNativeObject<Worker>(V8ClassIndex::WORKER, args.Holder()); - RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(toWebCoreString(args[0])); + Worker* worker = V8Worker::toNative(args.Holder()); + RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(args[0]); 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 af647cd..e31e05f 100644 --- a/WebCore/bindings/v8/custom/V8XMLHttpRequestConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8XMLHttpRequestConstructor.cpp @@ -29,19 +29,19 @@ */ #include "config.h" +#include "V8XMLHttpRequest.h" #include "Frame.h" #include "V8Binding.h" #include "V8CustomBinding.h" #include "V8Proxy.h" #include "V8Utilities.h" -#include "XMLHttpRequest.h" #include "WorkerContext.h" #include "WorkerContextExecutionProxy.h" namespace WebCore { -CALLBACK_FUNC_DECL(XMLHttpRequestConstructor) +v8::Handle<v8::Value> V8XMLHttpRequest::constructorCallback(const v8::Arguments& args) { INC_STATS("DOM.XMLHttpRequest.Constructor"); diff --git a/WebCore/bindings/v8/custom/V8XMLHttpRequestCustom.cpp b/WebCore/bindings/v8/custom/V8XMLHttpRequestCustom.cpp index c3e4645..d7cdcd1 100644 --- a/WebCore/bindings/v8/custom/V8XMLHttpRequestCustom.cpp +++ b/WebCore/bindings/v8/custom/V8XMLHttpRequestCustom.cpp @@ -29,32 +29,33 @@ */ #include "config.h" -#include "XMLHttpRequest.h" +#include "V8XMLHttpRequest.h" #include "Frame.h" #include "V8Binding.h" +#include "V8Blob.h" #include "V8CustomBinding.h" #include "V8Document.h" -#include "V8File.h" #include "V8HTMLDocument.h" #include "V8Proxy.h" #include "V8Utilities.h" #include "WorkerContext.h" #include "WorkerContextExecutionProxy.h" +#include "XMLHttpRequest.h" namespace WebCore { -ACCESSOR_GETTER(XMLHttpRequestResponseText) +v8::Handle<v8::Value> V8XMLHttpRequest::responseTextAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.XMLHttpRequest.responsetext._get"); - XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + XMLHttpRequest* xmlHttpRequest = V8XMLHttpRequest::toNative(info.Holder()); return xmlHttpRequest->responseText().v8StringOrNull(); } -CALLBACK_FUNC_DECL(XMLHttpRequestAddEventListener) +v8::Handle<v8::Value> V8XMLHttpRequest::addEventListenerCallback(const v8::Arguments& args) { INC_STATS("DOM.XMLHttpRequest.addEventListener()"); - XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); + XMLHttpRequest* xmlHttpRequest = V8XMLHttpRequest::toNative(args.Holder()); RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(xmlHttpRequest, args[1], false, ListenerFindOrCreate); if (listener) { @@ -62,15 +63,15 @@ CALLBACK_FUNC_DECL(XMLHttpRequestAddEventListener) bool useCapture = args[2]->BooleanValue(); xmlHttpRequest->addEventListener(type, listener, useCapture); - createHiddenDependency(args.Holder(), args[1], V8Custom::kXMLHttpRequestCacheIndex); + createHiddenDependency(args.Holder(), args[1], cacheIndex); } return v8::Undefined(); } -CALLBACK_FUNC_DECL(XMLHttpRequestRemoveEventListener) +v8::Handle<v8::Value> V8XMLHttpRequest::removeEventListenerCallback(const v8::Arguments& args) { INC_STATS("DOM.XMLHttpRequest.removeEventListener()"); - XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); + XMLHttpRequest* xmlHttpRequest = V8XMLHttpRequest::toNative(args.Holder()); RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(xmlHttpRequest, args[1], false, ListenerFindOnly); if (listener) { @@ -78,13 +79,13 @@ CALLBACK_FUNC_DECL(XMLHttpRequestRemoveEventListener) bool useCapture = args[2]->BooleanValue(); xmlHttpRequest->removeEventListener(type, listener.get(), useCapture); - removeHiddenDependency(args.Holder(), args[1], V8Custom::kXMLHttpRequestCacheIndex); + removeHiddenDependency(args.Holder(), args[1], cacheIndex); } return v8::Undefined(); } -CALLBACK_FUNC_DECL(XMLHttpRequestOpen) +v8::Handle<v8::Value> V8XMLHttpRequest::openCallback(const v8::Arguments& args) { INC_STATS("DOM.XMLHttpRequest.open()"); // Four cases: @@ -96,7 +97,7 @@ CALLBACK_FUNC_DECL(XMLHttpRequestOpen) if (args.Length() < 2) return throwError("Not enough arguments", V8Proxy::SyntaxError); - XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); + XMLHttpRequest* xmlHttpRequest = V8XMLHttpRequest::toNative(args.Holder()); String method = toWebCoreString(args[0]); String urlstring = toWebCoreString(args[1]); @@ -133,10 +134,10 @@ static bool IsDocumentType(v8::Handle<v8::Value> value) return V8Document::HasInstance(value) || V8HTMLDocument::HasInstance(value); } -CALLBACK_FUNC_DECL(XMLHttpRequestSend) +v8::Handle<v8::Value> V8XMLHttpRequest::sendCallback(const v8::Arguments& args) { INC_STATS("DOM.XMLHttpRequest.send()"); - XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); + XMLHttpRequest* xmlHttpRequest = V8XMLHttpRequest::toNative(args.Holder()); ExceptionCode ec = 0; if (args.Length() < 1) @@ -145,14 +146,14 @@ CALLBACK_FUNC_DECL(XMLHttpRequestSend) v8::Handle<v8::Value> arg = args[0]; if (IsDocumentType(arg)) { v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg); - Document* document = V8DOMWrapper::convertDOMWrapperToNode<Document>(object); + Document* document = V8Document::toNative(object); ASSERT(document); xmlHttpRequest->send(document, ec); - } else if (V8File::HasInstance(arg)) { + } else if (V8Blob::HasInstance(arg)) { v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg); - File* file = V8DOMWrapper::convertDOMWrapperToNative<File>(object); - ASSERT(file); - xmlHttpRequest->send(file, ec); + Blob* blob = V8Blob::toNative(object); + ASSERT(blob); + xmlHttpRequest->send(blob, ec); } else xmlHttpRequest->send(toWebCoreStringWithNullCheck(arg), ec); } @@ -163,12 +164,13 @@ CALLBACK_FUNC_DECL(XMLHttpRequestSend) return v8::Undefined(); } -CALLBACK_FUNC_DECL(XMLHttpRequestSetRequestHeader) { +v8::Handle<v8::Value> V8XMLHttpRequest::setRequestHeaderCallback(const v8::Arguments& args) +{ INC_STATS("DOM.XMLHttpRequest.setRequestHeader()"); if (args.Length() < 2) return throwError("Not enough arguments", V8Proxy::SyntaxError); - XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); + XMLHttpRequest* xmlHttpRequest = V8XMLHttpRequest::toNative(args.Holder()); ExceptionCode ec = 0; String header = toWebCoreString(args[0]); String value = toWebCoreString(args[1]); @@ -178,13 +180,13 @@ CALLBACK_FUNC_DECL(XMLHttpRequestSetRequestHeader) { return v8::Undefined(); } -CALLBACK_FUNC_DECL(XMLHttpRequestGetResponseHeader) +v8::Handle<v8::Value> V8XMLHttpRequest::getResponseHeaderCallback(const v8::Arguments& args) { INC_STATS("DOM.XMLHttpRequest.getResponseHeader()"); if (args.Length() < 1) return throwError("Not enough arguments", V8Proxy::SyntaxError); - XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); + XMLHttpRequest* xmlHttpRequest = V8XMLHttpRequest::toNative(args.Holder()); ExceptionCode ec = 0; String header = toWebCoreString(args[0]); String result = xmlHttpRequest->getResponseHeader(header, ec); @@ -193,19 +195,19 @@ CALLBACK_FUNC_DECL(XMLHttpRequestGetResponseHeader) return v8StringOrNull(result); } -CALLBACK_FUNC_DECL(XMLHttpRequestOverrideMimeType) +v8::Handle<v8::Value> V8XMLHttpRequest::overrideMimeTypeCallback(const v8::Arguments& args) { INC_STATS("DOM.XMLHttpRequest.overrideMimeType()"); if (args.Length() < 1) return throwError("Not enough arguments", V8Proxy::SyntaxError); - XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); + XMLHttpRequest* xmlHttpRequest = V8XMLHttpRequest::toNative(args.Holder()); String value = toWebCoreString(args[0]); xmlHttpRequest->overrideMimeType(value); return v8::Undefined(); } -CALLBACK_FUNC_DECL(XMLHttpRequestDispatchEvent) +v8::Handle<v8::Value> V8XMLHttpRequest::dispatchEventCallback(const v8::Arguments& args) { INC_STATS("DOM.XMLHttpRequest.dispatchEvent()"); return v8::Undefined(); diff --git a/WebCore/bindings/v8/custom/V8XMLHttpRequestUploadCustom.cpp b/WebCore/bindings/v8/custom/V8XMLHttpRequestUploadCustom.cpp index 9323f71..0690189 100644 --- a/WebCore/bindings/v8/custom/V8XMLHttpRequestUploadCustom.cpp +++ b/WebCore/bindings/v8/custom/V8XMLHttpRequestUploadCustom.cpp @@ -29,7 +29,7 @@ */ #include "config.h" -#include "XMLHttpRequestUpload.h" +#include "V8XMLHttpRequestUpload.h" #include "ExceptionCode.h" #include "V8Binding.h" @@ -37,15 +37,16 @@ #include "V8Proxy.h" #include "V8Utilities.h" #include "XMLHttpRequest.h" +#include "XMLHttpRequestUpload.h" #include <wtf/Assertions.h> namespace WebCore { -CALLBACK_FUNC_DECL(XMLHttpRequestUploadAddEventListener) +v8::Handle<v8::Value> V8XMLHttpRequestUpload::addEventListenerCallback(const v8::Arguments& args) { INC_STATS("DOM.XMLHttpRequestUpload.addEventListener()"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, args.Holder()); + XMLHttpRequestUpload* xmlHttpRequestUpload = V8XMLHttpRequestUpload::toNative(args.Holder()); XMLHttpRequest* xmlHttpRequest = xmlHttpRequestUpload->associatedXMLHttpRequest(); @@ -55,15 +56,15 @@ CALLBACK_FUNC_DECL(XMLHttpRequestUploadAddEventListener) bool useCapture = args[2]->BooleanValue(); xmlHttpRequestUpload->addEventListener(type, listener, useCapture); - createHiddenDependency(args.Holder(), args[1], V8Custom::kXMLHttpRequestCacheIndex); + createHiddenDependency(args.Holder(), args[1], cacheIndex); } return v8::Undefined(); } -CALLBACK_FUNC_DECL(XMLHttpRequestUploadRemoveEventListener) +v8::Handle<v8::Value> V8XMLHttpRequestUpload::removeEventListenerCallback(const v8::Arguments& args) { INC_STATS("DOM.XMLHttpRequestUpload.removeEventListener()"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, args.Holder()); + XMLHttpRequestUpload* xmlHttpRequestUpload = V8XMLHttpRequestUpload::toNative(args.Holder()); XMLHttpRequest* xmlHttpRequest = xmlHttpRequestUpload->associatedXMLHttpRequest(); @@ -73,13 +74,13 @@ CALLBACK_FUNC_DECL(XMLHttpRequestUploadRemoveEventListener) bool useCapture = args[2]->BooleanValue(); xmlHttpRequestUpload->removeEventListener(type, listener.get(), useCapture); - removeHiddenDependency(args.Holder(), args[1], V8Custom::kXMLHttpRequestCacheIndex); + removeHiddenDependency(args.Holder(), args[1], cacheIndex); } return v8::Undefined(); } -CALLBACK_FUNC_DECL(XMLHttpRequestUploadDispatchEvent) +v8::Handle<v8::Value> V8XMLHttpRequestUpload::dispatchEventCallback(const v8::Arguments& args) { INC_STATS("DOM.XMLHttpRequestUpload.dispatchEvent()"); return throwError(NOT_SUPPORTED_ERR); diff --git a/WebCore/bindings/v8/custom/V8XSLTProcessorCustom.cpp b/WebCore/bindings/v8/custom/V8XSLTProcessorCustom.cpp index 1ad7d4a..fd0305a 100644 --- a/WebCore/bindings/v8/custom/V8XSLTProcessorCustom.cpp +++ b/WebCore/bindings/v8/custom/V8XSLTProcessorCustom.cpp @@ -29,7 +29,7 @@ */ #include "config.h" -#include "XSLTProcessor.h" +#include "V8XSLTProcessor.h" #include "Document.h" #include "DocumentFragment.h" @@ -40,57 +40,58 @@ #include "V8Document.h" #include "V8Node.h" #include "V8Proxy.h" +#include "XSLTProcessor.h" #include <wtf/RefPtr.h> namespace WebCore { -CALLBACK_FUNC_DECL(XSLTProcessorConstructor) +v8::Handle<v8::Value> V8XSLTProcessor::constructorCallback(const v8::Arguments& args) { INC_STATS("DOM.XSLTProcessor.Constructor"); return V8Proxy::constructDOMObject<V8ClassIndex::XSLTPROCESSOR, XSLTProcessor>(args); } -CALLBACK_FUNC_DECL(XSLTProcessorImportStylesheet) +v8::Handle<v8::Value> V8XSLTProcessor::importStylesheetCallback(const v8::Arguments& args) { INC_STATS("DOM.XSLTProcessor.importStylesheet"); if (!V8Node::HasInstance(args[0])) return v8::Undefined(); - XSLTProcessor* imp = V8DOMWrapper::convertToNativeObject<XSLTProcessor>(V8ClassIndex::XSLTPROCESSOR, args.Holder()); + XSLTProcessor* imp = V8XSLTProcessor::toNative(args.Holder()); - Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])); + Node* node = V8Node::toNative(v8::Handle<v8::Object>::Cast(args[0])); imp->importStylesheet(node); return v8::Undefined(); } -CALLBACK_FUNC_DECL(XSLTProcessorTransformToFragment) +v8::Handle<v8::Value> V8XSLTProcessor::transformToFragmentCallback(const v8::Arguments& args) { INC_STATS("DOM.XSLTProcessor.transformToFragment"); if (!V8Node::HasInstance(args[0]) || !V8Document::HasInstance(args[1])) return v8::Undefined(); - XSLTProcessor* imp = V8DOMWrapper::convertToNativeObject<XSLTProcessor>(V8ClassIndex::XSLTPROCESSOR, args.Holder()); + XSLTProcessor* imp = V8XSLTProcessor::toNative(args.Holder()); - Node* source = V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])); - Document* owner = V8DOMWrapper::convertDOMWrapperToNode<Document>(v8::Handle<v8::Object>::Cast(args[1])); + Node* source = V8Node::toNative(v8::Handle<v8::Object>::Cast(args[0])); + Document* owner = V8Document::toNative(v8::Handle<v8::Object>::Cast(args[1])); RefPtr<DocumentFragment> result = imp->transformToFragment(source, owner); return V8DOMWrapper::convertNodeToV8Object(result.release()); } -CALLBACK_FUNC_DECL(XSLTProcessorTransformToDocument) +v8::Handle<v8::Value> V8XSLTProcessor::transformToDocumentCallback(const v8::Arguments& args) { INC_STATS("DOM.XSLTProcessor.transformToDocument"); if (!V8Node::HasInstance(args[0])) return v8::Undefined(); - XSLTProcessor* imp = V8DOMWrapper::convertToNativeObject<XSLTProcessor>(V8ClassIndex::XSLTPROCESSOR, args.Holder()); + XSLTProcessor* imp = V8XSLTProcessor::toNative(args.Holder()); - Node* source = V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])); + Node* source = V8Node::toNative(v8::Handle<v8::Object>::Cast(args[0])); if (!source) return v8::Undefined(); @@ -102,13 +103,13 @@ CALLBACK_FUNC_DECL(XSLTProcessorTransformToDocument) } -CALLBACK_FUNC_DECL(XSLTProcessorSetParameter) +v8::Handle<v8::Value> V8XSLTProcessor::setParameterCallback(const v8::Arguments& args) { INC_STATS("DOM.XSLTProcessor.setParameter"); if (isUndefinedOrNull(args[1]) || isUndefinedOrNull(args[2])) return v8::Undefined(); - XSLTProcessor* imp = V8DOMWrapper::convertToNativeObject<XSLTProcessor>(V8ClassIndex::XSLTPROCESSOR, args.Holder()); + XSLTProcessor* imp = V8XSLTProcessor::toNative(args.Holder()); String namespaceURI = toWebCoreString(args[0]); String localName = toWebCoreString(args[1]); @@ -119,13 +120,13 @@ CALLBACK_FUNC_DECL(XSLTProcessorSetParameter) } -CALLBACK_FUNC_DECL(XSLTProcessorGetParameter) +v8::Handle<v8::Value> V8XSLTProcessor::getParameterCallback(const v8::Arguments& args) { INC_STATS("DOM.XSLTProcessor.getParameter"); if (isUndefinedOrNull(args[1])) return v8::Undefined(); - XSLTProcessor* imp = V8DOMWrapper::convertToNativeObject<XSLTProcessor>(V8ClassIndex::XSLTPROCESSOR, args.Holder()); + XSLTProcessor* imp = V8XSLTProcessor::toNative(args.Holder()); String namespaceURI = toWebCoreString(args[0]); String localName = toWebCoreString(args[1]); @@ -136,13 +137,13 @@ CALLBACK_FUNC_DECL(XSLTProcessorGetParameter) return v8String(result); } -CALLBACK_FUNC_DECL(XSLTProcessorRemoveParameter) +v8::Handle<v8::Value> V8XSLTProcessor::removeParameterCallback(const v8::Arguments& args) { INC_STATS("DOM.XSLTProcessor.removeParameter"); if (isUndefinedOrNull(args[1])) return v8::Undefined(); - XSLTProcessor* imp = V8DOMWrapper::convertToNativeObject<XSLTProcessor>(V8ClassIndex::XSLTPROCESSOR, args.Holder()); + XSLTProcessor* imp = V8XSLTProcessor::toNative(args.Holder()); String namespaceURI = toWebCoreString(args[0]); String localName = toWebCoreString(args[1]); diff --git a/WebCore/bindings/v8/specialization/V8BindingDOMWindow.h b/WebCore/bindings/v8/specialization/V8BindingDOMWindow.h new file mode 100644 index 0000000..0c4069f --- /dev/null +++ b/WebCore/bindings/v8/specialization/V8BindingDOMWindow.h @@ -0,0 +1,59 @@ +/* + * 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. + */ + +#ifndef V8BindingDOMWindow_h +#define V8BindingDOMWindow_h + +#include "BindingDOMWindow.h" +#include "GenericBinding.h" +#include "V8Proxy.h" + +namespace WebCore { + +class V8Binding; + +class V8BindingDOMWindow : public BindingDOMWindow<V8Binding> { +public: + static void storeDialogArgs(State<V8Binding>*, Frame* newFrame, v8::Handle<v8::Value> dialogArgs) + { + // Set dialog arguments on the global object of the new frame. + if (!dialogArgs.IsEmpty()) { + v8::Local<v8::Context> context = V8Proxy::context(newFrame); + if (!context.IsEmpty()) { + v8::Context::Scope scope(context); + context->Global()->Set(v8::String::New("dialogArguments"), dialogArgs); + } + } + } +}; + +} // namespace WebCore + +#endif // V8BindingDOMWindow_h diff --git a/WebCore/bindings/v8/specialization/V8BindingState.cpp b/WebCore/bindings/v8/specialization/V8BindingState.cpp new file mode 100644 index 0000000..4710271 --- /dev/null +++ b/WebCore/bindings/v8/specialization/V8BindingState.cpp @@ -0,0 +1,61 @@ +/* + * 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 "V8BindingState.h" + +#include "V8Proxy.h" +#include <wtf/StdLibExtras.h> + +namespace WebCore { + +State<V8Binding>* State<V8Binding>::Only() +{ + DEFINE_STATIC_LOCAL(State, globalV8BindingState, ()); + return &globalV8BindingState; +} + +DOMWindow* State<V8Binding>::getActiveWindow() +{ + v8::Local<v8::Context> activeContext = v8::Context::GetCalling(); + if (activeContext.IsEmpty()) { + // There is a single activation record on the stack, so that must + // be the activeContext. + activeContext = v8::Context::GetCurrent(); + } + return V8Proxy::retrieveWindow(activeContext); +} + +void State<V8Binding>::immediatelyReportUnsafeAccessTo(Frame* target) +{ + V8Proxy::reportUnsafeAccessTo(target, V8Proxy::ReportNow); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/specialization/V8BindingState.h b/WebCore/bindings/v8/specialization/V8BindingState.h new file mode 100644 index 0000000..f305c14 --- /dev/null +++ b/WebCore/bindings/v8/specialization/V8BindingState.h @@ -0,0 +1,62 @@ +/* + * 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. + */ + +#ifndef V8BindingState_h +#define V8BindingState_h + +#include "GenericBinding.h" +#include "V8Binding.h" + +namespace WebCore { + +// Singleton implementation of State<V8Binding>. Uses V8's global data +// structures to return information about relevant execution state. +template <> +class State<V8Binding> : public State<GenericBinding> { +public: + // Singleton + static State* Only(); + + // The DOMWindow corresponding to the 'calling context' of execution. + DOMWindow* getActiveWindow(); + + // Reports an error message (without delay) if the security check fails. + static void immediatelyReportUnsafeAccessTo(Frame*); + +private: + explicit State() {} + ~State(); +}; + +typedef State<V8Binding> V8BindingState; + +} + +#endif // V8BindingState_h |