diff options
author | Feng Qian <fqian@google.com> | 2009-06-19 18:07:09 -0700 |
---|---|---|
committer | Feng Qian <fqian@google.com> | 2009-06-19 18:25:55 -0700 |
commit | 263a3894c3719057dcbd85b9094eba072da13511 (patch) | |
tree | 4def6f67b7419440763d17512fcd113b052b15b2 /V8Binding/binding | |
parent | deb47eadf0a66364e234e8e8031fec564ab49e41 (diff) | |
download | external_webkit-263a3894c3719057dcbd85b9094eba072da13511.zip external_webkit-263a3894c3719057dcbd85b9094eba072da13511.tar.gz external_webkit-263a3894c3719057dcbd85b9094eba072da13511.tar.bz2 |
Merged changed from Chromium r18043.
Need to delete V8MessagePortCustom.cpp.
Diffstat (limited to 'V8Binding/binding')
25 files changed, 732 insertions, 3286 deletions
diff --git a/V8Binding/binding/JSDOMBinding.cpp b/V8Binding/binding/JSDOMBinding.cpp deleted file mode 100644 index c72a92b..0000000 --- a/V8Binding/binding/JSDOMBinding.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2008, 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 "JSDOMBinding.h" - -#include "Document.h" -#include "Node.h" - -namespace WebCore { - -void updateDOMNodeDocument(Node* node, Document* oldDocument, - Document* newDocument) -{ - // We don't do anything here in V8 bindings -} - -ScriptState* scriptStateFromNode(Node* node) -{ - // This should be never reached with V8 bindings (WebKit only uses it - // for non-JS bindings) - ASSERT_NOT_REACHED(); - return 0; -} - -} // namespace WebCore diff --git a/V8Binding/binding/JSDOMBinding.h b/V8Binding/binding/JSDOMBinding.h deleted file mode 100644 index 8ed5602..0000000 --- a/V8Binding/binding/JSDOMBinding.h +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) 2008, 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. - -// Masquerade to pretend that we support JSC namespace and avoid unforking -// This is not a reimplementation of the JSC namespace. It's just enough code -// to avoid #ifdefs in WebKit code. - -#ifndef JSDOMBinding_h -#define JSDOMBinding_h - -namespace WebCore { - class Node; - class Document; - class ScriptState; - - void updateDOMNodeDocument(Node*, Document* oldDocument, - Document* newDocument); - - ScriptState* scriptStateFromNode(Node*); - -} - - -#endif // JSDOMBinding_h diff --git a/V8Binding/binding/JSXPathNSResolver.cpp b/V8Binding/binding/JSXPathNSResolver.cpp index 2fb2849..5174809 100644 --- a/V8Binding/binding/JSXPathNSResolver.cpp +++ b/V8Binding/binding/JSXPathNSResolver.cpp @@ -58,7 +58,7 @@ String JSXPathNSResolver::lookupNamespaceURI(const String& prefix) { } if (lookupNamespaceURIFunc.IsEmpty() && !m_resolver->IsFunction()) { - Frame* frame = V8Proxy::retrieveActiveFrame(); + Frame* frame = V8Proxy::retrieveFrameForEnteredContext(); log_info(frame, "XPathNSResolver does not have a lookupNamespaceURI method.", String()); return String(); } @@ -82,7 +82,7 @@ String JSXPathNSResolver::lookupNamespaceURI(const String& prefix) { return String(); } - return ToWebCoreString(retval); + return valueToStringWithNullCheck(retval); } } diff --git a/V8Binding/binding/NPV8Object.cpp b/V8Binding/binding/NPV8Object.cpp index defe6bf..e7ce792 100644 --- a/V8Binding/binding/NPV8Object.cpp +++ b/V8Binding/binding/NPV8Object.cpp @@ -491,10 +491,40 @@ bool NPN_Construct(NPP npp, NPObject* npobj, const NPVariant* args, uint32_t arg if (!npobj) return false; - // FIXME(estade): implement this case. if (npobj->_class == npScriptObjectClass) { - VOID_TO_NPVARIANT(*result); - return false; + V8NPObject *object = reinterpret_cast<V8NPObject*>(npobj); + + v8::HandleScope handleScope; + v8::Handle<v8::Context> context = getV8Context(npp, npobj); + if (context.IsEmpty()) + return false; + v8::Context::Scope scope(context); + + // Lookup the constructor function. + v8::Handle<v8::Object> ctorObj(object->v8Object); + if (!ctorObj->IsFunction()) + return false; + + // Call the constructor. + v8::Local<v8::Value> resultObj; + v8::Handle<v8::Function> ctor(v8::Function::Cast(*ctorObj)); + if (!ctor->IsNull()) { + WebCore::V8Proxy* proxy = GetV8Proxy(npobj); + ASSERT(proxy); + + // Create list of args to pass to v8. + v8::Handle<v8::Value>* argv = listFromVariantArgs(args, argCount, npobj); + resultObj = proxy->NewInstance(ctor, argCount, argv); + delete[] argv; + } + + // If we had an error return false. + if (resultObj.IsEmpty()) + return false; + + // Convert the result back to an NPVariant. + convertV8ObjectToNPVariant(resultObj, npobj, result); + return true; } if (NP_CLASS_STRUCT_VERSION_HAS_CTOR(npobj->_class) && npobj->_class->construct) diff --git a/V8Binding/binding/ScriptController.cpp b/V8Binding/binding/ScriptController.cpp deleted file mode 100644 index e53606e..0000000 --- a/V8Binding/binding/ScriptController.cpp +++ /dev/null @@ -1,451 +0,0 @@ -// Copyright (c) 2008, 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 "ScriptController.h" - -#if PLATFORM(CHROMIUM) -#include "ChromiumBridge.h" -#endif - -#include "CString.h" -#include "Document.h" -#include "DOMWindow.h" -#include "Event.h" -#include "EventListener.h" -#include "EventNames.h" -#include "Frame.h" -#include "Node.h" -#include "NotImplemented.h" -#include "npruntime_priv.h" -#include "NPV8Object.h" -#include "ScriptSourceCode.h" -#include "PluginView.h" -#include "Widget.h" - -#include "v8_proxy.h" -#include "v8_binding.h" -#include "V8NPObject.h" - -NPRuntimeFunctions npruntime_functions = { - NPN_GetStringIdentifier, - NPN_GetStringIdentifiers, - NPN_GetIntIdentifier, - NPN_IdentifierIsString, - NPN_UTF8FromIdentifier, - NPN_IntFromIdentifier, - NPN_CreateObject, - NPN_RetainObject, - NPN_ReleaseObject, - NPN_Invoke, - NPN_InvokeDefault, - NPN_Evaluate, - NPN_GetProperty, - NPN_SetProperty, - NPN_RemoveProperty, - NPN_HasProperty, - NPN_HasMethod, - NPN_ReleaseVariantValue, - NPN_SetException -}; - - -namespace WebCore { - -void ScriptController::setFlags(const char* str, int length) -{ - v8::V8::SetFlagsFromString(str, length); -} - -Frame* ScriptController::retrieveActiveFrame() -{ - return V8Proxy::retrieveActiveFrame(); -} - -bool ScriptController::isSafeScript(Frame* target) -{ - return V8Proxy::CanAccessFrame(target, true); -} - -void ScriptController::gcProtectJSWrapper(void* dom_object) -{ - V8Proxy::GCProtect(dom_object); -} - -void ScriptController::gcUnprotectJSWrapper(void* dom_object) -{ - V8Proxy::GCUnprotect(dom_object); -} - -ScriptController::ScriptController(Frame* frame) - : m_frame(frame) - , m_sourceURL(0) - , m_processingTimerCallback(false) - , m_paused(false) - , m_proxy(new V8Proxy(frame)) -#if ENABLE(NETSCAPE_PLUGIN_API) - , m_windowScriptNPObject(0) -#endif -{ -} - -ScriptController::~ScriptController() -{ -} - -void ScriptController::clearScriptObjects() -{ - PluginObjectMap::iterator it = m_pluginObjects.begin(); - for (; it != m_pluginObjects.end(); ++it) { - _NPN_UnregisterObject(it->second); - NPN_ReleaseObject(it->second); - } - m_pluginObjects.clear(); - -#if ENABLE(NETSCAPE_PLUGIN_API) - if (m_windowScriptNPObject) { - // Call _NPN_DeallocateObject() instead of _NPN_ReleaseObject() so that we don't leak if a plugin fails to release the window - // script object properly. - // This shouldn't cause any problems for plugins since they should have already been stopped and destroyed at this point. - _NPN_DeallocateObject(m_windowScriptNPObject); - m_windowScriptNPObject = 0; - } -#endif -} - -void ScriptController::updateSecurityOrigin() -{ - m_proxy->updateSecurityOrigin(); -} - -void ScriptController::updatePlatformScriptObjects() -{ - notImplemented(); -} - -// Disconnect the proxy from its owner frame; -void ScriptController::disconnectFrame() -{ - m_proxy->disconnectFrame(); -} - -bool ScriptController::processingUserGesture() const -{ - Frame* active_frame = V8Proxy::retrieveActiveFrame(); - // No script is running, must be run by users. - if (!active_frame) - return true; - - V8Proxy* active_proxy = active_frame->script()->proxy(); - - v8::HandleScope handle_scope; - v8::Handle<v8::Context> context = V8Proxy::GetContext(active_frame); - // TODO(fqian): find all cases context can be empty: - // 1) JS is disabled; - // 2) page is NULL; - if (context.IsEmpty()) - return true; - - v8::Context::Scope scope(context); - - v8::Handle<v8::Object> global = context->Global(); - v8::Handle<v8::Value> jsevent = global->Get(v8::String::NewSymbol("event")); - Event* event = V8Proxy::ToNativeEvent(jsevent); - - // Based on code from kjs_bindings.cpp. - // Note: This is more liberal than Firefox's implementation. - if (event) { - const AtomicString& type = event->type(); - bool event_ok = - // mouse events - type == eventNames().clickEvent || - type == eventNames().mousedownEvent || - type == eventNames().mouseupEvent || - type == eventNames().dblclickEvent || - // keyboard events - type == eventNames().keydownEvent || - type == eventNames().keypressEvent || - type == eventNames().keyupEvent || - // other accepted events - type == eventNames().selectEvent || - type == eventNames().changeEvent || - type == eventNames().focusEvent || - type == eventNames().blurEvent || - type == eventNames().submitEvent; - - if (event_ok) - return true; - } else if (active_proxy->inlineCode() && !active_proxy->timerCallback()) - // This is the <a href="javascript:window.open('...')> case -> we let it - // through - return true; - - // This is the <script>window.open(...)</script> case or a timer callback -> - // block it - return false; -} - -void ScriptController::evaluateInNewContext( - const Vector<ScriptSourceCode>& sources) { - m_proxy->evaluateInNewContext(sources); -} - -// Evaluate a script file in the environment of this proxy. -ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode) -{ - v8::HandleScope hs; - v8::Handle<v8::Context> context = V8Proxy::GetContext(m_proxy->frame()); - if (context.IsEmpty()) - return ScriptValue(); - - v8::Context::Scope scope(context); - v8::Local<v8::Value> obj = m_proxy->evaluate(sourceCode, NULL); - - if (obj.IsEmpty() || obj->IsUndefined()) - return ScriptValue(); - - return ScriptValue(obj); -} - -void ScriptController::disposeJSResult(v8::Persistent<v8::Value> result) -{ - result.Dispose(); - result.Clear(); -} - -PassRefPtr<EventListener> ScriptController::createInlineEventListener( - const String& functionName, const String& code, Node* node) -{ - return m_proxy->createInlineEventListener(functionName, code, node); -} - -#if ENABLE(SVG) -PassRefPtr<EventListener> ScriptController::createSVGEventHandler( - const String& functionName, const String& code, Node* node) -{ - return m_proxy->createSVGEventHandler(functionName, code, node); -} -#endif - -void ScriptController::setEventHandlerLineno(int lineno) -{ - m_proxy->setEventHandlerLineno(lineno); -} - -void ScriptController::finishedWithEvent(Event* evt) -{ - m_proxy->finishedWithEvent(evt); -} - -// Create a V8 object with an interceptor of NPObjectPropertyGetter -void ScriptController::BindToWindowObject(Frame* frame, const String& key, NPObject* object) -{ - v8::HandleScope handle_scope; - - v8::Handle<v8::Context> context = V8Proxy::GetContext(frame); - if (context.IsEmpty()) - return; - - v8::Context::Scope scope(context); - - v8::Handle<v8::Object> value = CreateV8ObjectForNPObject(object, NULL); - - // Attach to the global object - v8::Handle<v8::Object> global = context->Global(); - global->Set(v8String(key), value); -} - -void ScriptController::collectGarbage() -{ - v8::HandleScope hs; - v8::Handle<v8::Context> context = V8Proxy::GetContext(m_proxy->frame()); - if (context.IsEmpty()) - return; - - v8::Context::Scope scope(context); - - m_proxy->evaluate(ScriptSourceCode("if (window.gc) void(gc());"), NULL); -} - -NPRuntimeFunctions* ScriptController::functions() -{ - return &npruntime_functions; -} - - -bool ScriptController::haveInterpreter() const -{ - return m_proxy->ContextInitialized(); -} - -bool ScriptController::isEnabled() const -{ - return m_proxy->isEnabled(); -} - -PassScriptInstance ScriptController::createScriptInstanceForWidget(Widget* widget) -{ - ASSERT(widget != 0); - -#if PLATFORM(CHROMIUM) - if (widget->isFrameView()) - return 0; - - NPObject* npObject = ChromiumBridge::pluginScriptableObject(widget); -#elif PLATFORM(ANDROID) - if (!widget->isPluginView()) - return 0; - - PluginView* pluginView = static_cast<PluginView*>(widget); - NPObject* npObject = pluginView->getNPObject(); -#endif - if (!npObject) - return 0; - // Frame Memory Management for NPObjects - // ------------------------------------- - // NPObjects are treated differently than other objects wrapped by JS. - // NPObjects can be created either by the browser (e.g. the main - // window object) or by the plugin (the main plugin object - // for a HTMLEmbedElement). Further, - // unlike most DOM Objects, the frame is especially careful to ensure - // NPObjects terminate at frame teardown because if a plugin leaks a - // reference, it could leak its objects (or the browser's objects). - // - // The Frame maintains a list of plugin objects (m_pluginObjects) - // which it can use to quickly find the wrapped embed object. - // - // Inside the NPRuntime, we've added a few methods for registering - // wrapped NPObjects. The purpose of the registration is because - // javascript garbage collection is non-deterministic, yet we need to - // be able to tear down the plugin objects immediately. When an object - // is registered, javascript can use it. When the object is destroyed, - // or when the object's "owning" object is destroyed, the object will - // be un-registered, and the javascript engine must not use it. - // - // Inside the javascript engine, the engine can keep a reference to the - // NPObject as part of its wrapper. However, before accessing the object - // it must consult the NPN_Registry. - - v8::Local<v8::Object> wrapper = CreateV8ObjectForNPObject(npObject, NULL); - - // Track the plugin object. We've been given a reference to the object. - m_pluginObjects.set(widget, npObject); - - return V8ScriptInstance::create(wrapper); -} - -void ScriptController::cleanupScriptObjectsForPlugin(void* nativeHandle) -{ - PluginObjectMap::iterator it = m_pluginObjects.find(nativeHandle); - if (it == m_pluginObjects.end()) - return; - _NPN_UnregisterObject(it->second); - NPN_ReleaseObject(it->second); - m_pluginObjects.remove(it); -} - -static NPObject* createNoScriptObject() -{ - notImplemented(); - return 0; -} - -static NPObject* createScriptObject(Frame* frame) -{ - v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::GetContext(frame); - if (context.IsEmpty()) - return createNoScriptObject(); - - v8::Context::Scope scope(context); - DOMWindow* window = frame->domWindow(); - v8::Handle<v8::Value> global = V8Proxy::ToV8Object(V8ClassIndex::DOMWINDOW, window); - ASSERT(global->IsObject()); - return npCreateV8ScriptObject(0, v8::Handle<v8::Object>::Cast(global), window); -} - -NPObject* ScriptController::windowScriptNPObject() -{ - if (m_windowScriptNPObject) - return m_windowScriptNPObject; - - if (isEnabled()) { - // JavaScript is enabled, so there is a JavaScript window object. - // Return an NPObject bound to the window object. - m_windowScriptNPObject = createScriptObject(m_frame); - _NPN_RegisterObject(m_windowScriptNPObject, NULL); - } else { - // JavaScript is not enabled, so we cannot bind the NPObject to the - // JavaScript window object. Instead, we create an NPObject of a - // different class, one which is not bound to a JavaScript object. - m_windowScriptNPObject = createNoScriptObject(); - } - return m_windowScriptNPObject; -} - -NPObject* ScriptController::createScriptObjectForPluginElement(HTMLPlugInElement* plugin) -{ - // Can't create NPObjects when JavaScript is disabled - if (!isEnabled()) - return createNoScriptObject(); - - v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::GetContext(m_frame); - if (context.IsEmpty()) - return createNoScriptObject(); - v8::Context::Scope scope(context); - - DOMWindow* window = m_frame->domWindow(); - v8::Handle<v8::Value> v8plugin = V8Proxy::ToV8Object(V8ClassIndex::HTMLEMBEDELEMENT, plugin); - if (!v8plugin->IsObject()) - return createNoScriptObject(); - - return npCreateV8ScriptObject(0, v8::Handle<v8::Object>::Cast(v8plugin), window); -} - - -void ScriptController::clearWindowShell() -{ - // V8 binding expects ScriptController::clearWindowShell only be called - // when a frame is loading a new page. V8Proxy::clearForNavigation - // creates a new context for the new page. - m_proxy->clearForNavigation(); -} - -void ScriptController::attachDebugger(void*) -{ - notImplemented(); -} - -void ScriptController::updateDocument() -{ - m_proxy->updateDocument(); -} - -} // namespace WebCpre diff --git a/V8Binding/binding/ScriptController.h b/V8Binding/binding/ScriptController.h deleted file mode 100644 index 40534fb..0000000 --- a/V8Binding/binding/ScriptController.h +++ /dev/null @@ -1,271 +0,0 @@ -// Copyright 2008, 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. - -// An interface to abstract implementation differences -// for various Javascript engines. - -#ifndef ScriptController_h -#define ScriptController_h - -#include "HashMap.h" -#include "MessagePort.h" -#include "ScriptInstance.h" -#include "ScriptValue.h" -#include "SecurityOrigin.h" - -#if PLATFORM(CHROMIUM) -#include "bindings/npruntime.h" -#else -#include "bridge/npruntime.h" // use WebCore version -#endif - -#include <wtf/HashMap.h> -#include <wtf/Vector.h> - -#include "v8.h" -#include "v8_proxy.h" - -// JavaScript implementations which expose NPObject will need to implement -// these methods. -typedef void (*NPN_ReleaseVariantValueProcPtr) (NPVariant *variant); - -typedef NPIdentifier(*NPN_GetStringIdentifierProcPtr) (const NPUTF8 *name); -typedef void (*NPN_GetStringIdentifiersProcPtr) (const NPUTF8 **names, - int32_t nameCount, - NPIdentifier *identifiers); -typedef NPIdentifier(*NPN_GetIntIdentifierProcPtr) (int32_t intid); -typedef int32_t (*NPN_IntFromIdentifierProcPtr) (NPIdentifier identifier); -typedef bool (*NPN_IdentifierIsStringProcPtr) (NPIdentifier identifier); -typedef NPUTF8 * (*NPN_UTF8FromIdentifierProcPtr) (NPIdentifier identifier); - -typedef NPObject* (*NPN_CreateObjectProcPtr) (NPP, - NPClass *aClass); -typedef NPObject* (*NPN_RetainObjectProcPtr) (NPObject *obj); -typedef void (*NPN_ReleaseObjectProcPtr) (NPObject *obj); -typedef bool (*NPN_InvokeProcPtr) (NPP npp, - NPObject *obj, - NPIdentifier methodName, - const NPVariant *args, - unsigned argCount, - NPVariant *result); -typedef bool (*NPN_InvokeDefaultProcPtr) (NPP npp, - NPObject *obj, - const NPVariant *args, - unsigned argCount, - NPVariant *result); -typedef bool (*NPN_EvaluateProcPtr) (NPP npp, - NPObject *obj, - NPString *script, - NPVariant *result); -typedef bool (*NPN_GetPropertyProcPtr) (NPP npp, - NPObject *obj, - NPIdentifier propertyName, - NPVariant *result); -typedef bool (*NPN_SetPropertyProcPtr) (NPP npp, - NPObject *obj, - NPIdentifier propertyName, - const NPVariant *value); -typedef bool (*NPN_HasPropertyProcPtr) (NPP, - NPObject *npobj, - NPIdentifier propertyName); -typedef bool (*NPN_HasMethodProcPtr) (NPP npp, - NPObject *npobj, - NPIdentifier methodName); -typedef bool (*NPN_RemovePropertyProcPtr) (NPP npp, - NPObject *obj, - NPIdentifier propertyName); -typedef void (*NPN_SetExceptionProcPtr) (NPObject *obj, - const NPUTF8 *message); - -typedef struct _NPRuntimeFunctions { - NPN_GetStringIdentifierProcPtr getStringIdentifier; - NPN_GetStringIdentifiersProcPtr getStringIdentifiers; - NPN_GetIntIdentifierProcPtr getIntIdentifier; - NPN_IdentifierIsStringProcPtr identifierIsString; - NPN_UTF8FromIdentifierProcPtr utf8FromIdentifier; - NPN_IntFromIdentifierProcPtr intFromIdentifier; - NPN_CreateObjectProcPtr createObject; - NPN_RetainObjectProcPtr retainObject; - NPN_ReleaseObjectProcPtr releaseObject; - NPN_InvokeProcPtr invoke; - NPN_InvokeDefaultProcPtr invokeDefault; - NPN_EvaluateProcPtr evaluate; - NPN_GetPropertyProcPtr getProperty; - NPN_SetPropertyProcPtr setProperty; - NPN_RemovePropertyProcPtr removeProperty; - NPN_HasPropertyProcPtr hasProperty; - NPN_HasMethodProcPtr hasMethod; - NPN_ReleaseVariantValueProcPtr releaseVariantValue; - NPN_SetExceptionProcPtr setException; -} NPRuntimeFunctions; - -namespace WebCore { -class Document; -class EventListener; -class Event; -class Frame; -class HTMLPlugInElement; -class Node; -class ScriptSourceCode; -class String; -class Widget; - -typedef v8::Local<v8::Object> JSInstance; -typedef v8::Local<v8::Object> JSInstanceHandle; -typedef v8::Persistent<v8::Object> JSPersistentInstance; -typedef v8::Local<v8::Value> JSException; -typedef v8::Persistent<v8::Value> JSResult; - -class ScriptController { -public: - ScriptController(Frame*); - ~ScriptController(); - - // TODO(eseidel): V8Proxy should either be folded into ScriptController - // or this accessor should be made JSProxy* - V8Proxy* proxy() { return m_proxy.get(); } - - // 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 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>& sources); - - // JSC has a WindowShell object, but for V8, the ScriptController - // is the WindowShell. - bool haveWindowShell() const { return m_proxy->ContextInitialized(); } - - // Masquerade 'this' as the windowShell. - // This is a bit of a hack, but provides reasonable compatibility - // with what JSC does as well. - ScriptController* windowShell() { return this; } - - void disposeJSResult(JSResult result); - void collectGarbage(); - - PassRefPtr<EventListener> createInlineEventListener(const String& functionName, const String& code, Node*); -#if ENABLE(SVG) - PassRefPtr<EventListener> createSVGEventHandler(const String& functionName, const String& code, Node*); -#endif - - // Creates a property of the global object of a frame. - void BindToWindowObject(Frame*, const String& key, NPObject*); - - NPRuntimeFunctions* functions(); - - PassScriptInstance createScriptInstanceForWidget(Widget*); - - void disconnectFrame(); - - // Check if the javascript engine has been initialized. - bool haveInterpreter() const; - - bool isEnabled() const; - - // TODO(eseidel): void* is a compile hack - void attachDebugger(void*); - - // Create a NPObject wrapper for a JSObject - // NPObject *WrapScriptObject(NPP pluginId, JSObject* objectToWrap, - // JSRootObject* originRootObject, - // JSRootObject* rootObject); - - // --- Static methods assume we are running VM in single thread, --- - // --- and there is only one VM instance. --- - - // Returns the frame of the calling code is in. - // Not necessary the frame of this proxy. - // For example, JS code in frame A calls windowB.open(...). - // Window::open method has the frame pointer of B, but - // the execution context is in frame A, so it needs - // frame A's loader to complete URL. - static Frame* retrieveActiveFrame(); - - // Check whether it is safe to access a frame in another domain. - static bool isSafeScript(Frame* target); - - // Pass command-line flags to the JS engine - static void setFlags(const char* str, int length); - - // Protect and unprotect the JS wrapper from garbage collected. - static void gcProtectJSWrapper(void* object); - static void gcUnprotectJSWrapper(void* object); - - void finishedWithEvent(Event*); - void setEventHandlerLineno(int lineno); - - void setProcessingTimerCallback(bool b) { m_processingTimerCallback = b; } - bool processingUserGesture() const; - - void setPaused(bool b) { m_paused = b; } - bool isPaused() const { return m_paused; } - - const String* sourceURL() const { return m_sourceURL; } // 0 if we are not evaluating any script - - void clearWindowShell(); - void updateDocument(); - - void updateSecurityOrigin(); - void clearScriptObjects(); - void updatePlatformScriptObjects(); - void cleanupScriptObjectsForPlugin(void*); - -#if ENABLE(NETSCAPE_PLUGIN_API) - NPObject* createScriptObjectForPluginElement(HTMLPlugInElement*); - NPObject* windowScriptNPObject(); -#endif - -private: - Frame* m_frame; - const String* m_sourceURL; - - bool m_processingTimerCallback; - bool m_paused; - - OwnPtr<V8Proxy> m_proxy; - typedef HashMap<void*, 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; -#if ENABLE(NETSCAPE_PLUGIN_API) - NPObject* m_windowScriptNPObject; -#endif -}; - -} // namespace WebCore - -#endif // ScriptController_h diff --git a/V8Binding/binding/V8CanvasPixelArrayCustom.cpp b/V8Binding/binding/V8CanvasPixelArrayCustom.cpp deleted file mode 100644 index d5441a1..0000000 --- a/V8Binding/binding/V8CanvasPixelArrayCustom.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) 2009, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "config.h" - -#include "v8_binding.h" -#include "v8_custom.h" -#include "v8_proxy.h" - -#include "CanvasPixelArray.h" - -namespace WebCore { - -// Get the specified value from the pixel buffer and return it wrapped as a -// JavaScript Number object to V8. Accesses outside the valid pixel buffer -// range return "undefined". -INDEXED_PROPERTY_GETTER(CanvasPixelArray) { - INC_STATS("DOM.CanvasPixelArray.IndexedPropertyGetter"); - CanvasPixelArray* pixelBuffer = - V8Proxy::ToNativeObject<CanvasPixelArray>( - V8ClassIndex::CANVASPIXELARRAY, - info.Holder()); - - if ((index < 0) || (index >= pixelBuffer->length())) { - return v8::Undefined(); - } - unsigned char result; - if (!pixelBuffer->get(index, result)) { - return v8::Undefined(); - } - return v8::Number::New(result); -} - - -// Set the specified value in the pixel buffer. Accesses outside the valid pixel -// buffer range are silently ignored. -INDEXED_PROPERTY_SETTER(CanvasPixelArray) { - INC_STATS("DOM.CanvasPixelArray.IndexedPropertySetter"); - CanvasPixelArray* pixelBuffer = - V8Proxy::ToNativeObject<CanvasPixelArray>( - V8ClassIndex::CANVASPIXELARRAY, - info.Holder()); - - if ((index >= 0) && (index < pixelBuffer->length())) { - pixelBuffer->set(index, value->NumberValue()); - } - return value; -} - - -} // namespace WebCore diff --git a/V8Binding/binding/V8MessagePortCustom.cpp b/V8Binding/binding/V8MessagePortCustom.cpp index 6405b67..e69de29 100644 --- a/V8Binding/binding/V8MessagePortCustom.cpp +++ b/V8Binding/binding/V8MessagePortCustom.cpp @@ -1,239 +0,0 @@ -/* -* Copyright (C) 2009 Google Inc. All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are -* met: -* -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above -* copyright notice, this list of conditions and the following disclaimer -* in the documentation and/or other materials provided with the -* distribution. -* * Neither the name of Google Inc. nor the names of its -* contributors may be used to endorse or promote products derived from -* this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "config.h" - -#include "v8_binding.h" -#include "v8_custom.h" -#include "v8_proxy.h" - -#include "V8Document.h" -#include "V8HTMLDocument.h" -#include "V8ObjectEventListener.h" - -#include "ExceptionCode.h" -#include "MessagePort.h" - -namespace WebCore { - -// FIXME: merge these with XHR's CreateHiddenXHRDependency - -// Use an array to hold dependents. It works like a ref-counted scheme. -// A value can be added more than once to the xhr object. -static void CreateHiddenDependency(v8::Local<v8::Object> object, - v8::Local<v8::Value> value) -{ - ASSERT(V8Proxy::GetDOMWrapperType(object) == V8ClassIndex::MESSAGEPORT); - v8::Local<v8::Value> cache = object->GetInternalField(V8Custom::kMessagePortRequestCacheIndex); - if (cache->IsNull() || cache->IsUndefined()) { - cache = v8::Array::New(); - object->SetInternalField(V8Custom::kMessagePortRequestCacheIndex, cache); - } - - v8::Local<v8::Array> cacheArray = v8::Local<v8::Array>::Cast(cache); - cacheArray->Set(v8::Integer::New(cacheArray->Length()), value); -} - -static void RemoveHiddenDependency(v8::Local<v8::Object> object, - v8::Local<v8::Value> value) -{ - ASSERT(V8Proxy::GetDOMWrapperType(object) == V8ClassIndex::MESSAGEPORT); - v8::Local<v8::Value> cache = object->GetInternalField(V8Custom::kMessagePortRequestCacheIndex); - ASSERT(cache->IsArray()); - v8::Local<v8::Array> cacheArray = v8::Local<v8::Array>::Cast(cache); - for (int i = cacheArray->Length() - 1; i >= 0; i--) { - v8::Local<v8::Value> cached = cacheArray->Get(v8::Integer::New(i)); - if (cached->StrictEquals(value)) { - cacheArray->Delete(i); - return; - } - } - - // We should only get here if we try to remove an event listener that was - // never added. -} - -ACCESSOR_GETTER(MessagePortOnmessage) -{ - INC_STATS("DOM.MessagePort.onmessage._get"); - MessagePort* messagePort = V8Proxy::ToNativeObject<MessagePort>( - V8ClassIndex::MESSAGEPORT, info.Holder()); - if (messagePort->onmessage()) { - V8ObjectEventListener* listener = - static_cast<V8ObjectEventListener*>(messagePort->onmessage()); - v8::Local<v8::Object> v8Listener = listener->getListenerObject(); - return v8Listener; - } - return v8::Undefined(); -} - -ACCESSOR_SETTER(MessagePortOnmessage) -{ - INC_STATS("DOM.MessagePort.onmessage._set"); - MessagePort* messagePort = V8Proxy::ToNativeObject<MessagePort>( - V8ClassIndex::MESSAGEPORT, info.Holder()); - if (value->IsNull()) { - if (messagePort->onmessage()) { - V8ObjectEventListener* listener = - static_cast<V8ObjectEventListener*>(messagePort->onmessage()); - v8::Local<v8::Object> v8Listener = listener->getListenerObject(); - RemoveHiddenDependency(info.Holder(), v8Listener); - } - - // Clear the listener - messagePort->setOnmessage(0); - - } else { - V8Proxy* proxy = V8Proxy::retrieve(messagePort->scriptExecutionContext()); - if (!proxy) - return; - - RefPtr<EventListener> listener = - proxy->FindOrCreateObjectEventListener(value, false); - if (listener) { - messagePort->setOnmessage(listener); - CreateHiddenDependency(info.Holder(), value); - } - } -} - -ACCESSOR_GETTER(MessagePortOnclose) -{ - INC_STATS("DOM.MessagePort.onclose._get"); - MessagePort* messagePort = V8Proxy::ToNativeObject<MessagePort>( - V8ClassIndex::MESSAGEPORT, info.Holder()); - if (messagePort->onclose()) { - V8ObjectEventListener* listener = - static_cast<V8ObjectEventListener*>(messagePort->onclose()); - v8::Local<v8::Object> v8Listener = listener->getListenerObject(); - return v8Listener; - } - return v8::Undefined(); -} - -ACCESSOR_SETTER(MessagePortOnclose) -{ - INC_STATS("DOM.MessagePort.onclose._set"); - MessagePort* messagePort = V8Proxy::ToNativeObject<MessagePort>( - V8ClassIndex::MESSAGEPORT, info.Holder()); - if (value->IsNull()) { - if (messagePort->onclose()) { - V8ObjectEventListener* listener = - static_cast<V8ObjectEventListener*>(messagePort->onclose()); - v8::Local<v8::Object> v8Listener = listener->getListenerObject(); - RemoveHiddenDependency(info.Holder(), v8Listener); - } - - // Clear the listener - messagePort->setOnclose(0); - } else { - V8Proxy* proxy = V8Proxy::retrieve(messagePort->scriptExecutionContext()); - if (!proxy) - return; - - RefPtr<EventListener> listener = - proxy->FindOrCreateObjectEventListener(value, false); - if (listener) { - messagePort->setOnclose(listener); - CreateHiddenDependency(info.Holder(), value); - } - } -} - -CALLBACK_FUNC_DECL(MessagePortStartConversation) -{ - INC_STATS("DOM.MessagePort.StartConversation()"); - if (args.Length() < 1) { - V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "Not enough arguments"); - return v8::Undefined(); - } - - MessagePort* messagePort = V8Proxy::ToNativeObject<MessagePort>( - V8ClassIndex::MESSAGEPORT, args.Holder()); - - V8Proxy* proxy = V8Proxy::retrieve(messagePort->scriptExecutionContext()); - if (!proxy) - return v8::Undefined(); - - RefPtr<MessagePort> port = - messagePort->startConversation(messagePort->scriptExecutionContext(), - ToWebCoreString(args[0])); - v8::Handle<v8::Value> wrapper = - V8Proxy::ToV8Object(V8ClassIndex::MESSAGEPORT, port.get()); - return wrapper; -} - -CALLBACK_FUNC_DECL(MessagePortAddEventListener) -{ - INC_STATS("DOM.MessagePort.AddEventListener()"); - MessagePort* messagePort = V8Proxy::ToNativeObject<MessagePort>( - V8ClassIndex::MESSAGEPORT, args.Holder()); - - V8Proxy* proxy = V8Proxy::retrieve(messagePort->scriptExecutionContext()); - if (!proxy) - return v8::Undefined(); - - RefPtr<EventListener> listener = - proxy->FindOrCreateObjectEventListener(args[1], false); - if (listener) { - String type = ToWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - messagePort->addEventListener(type, listener, useCapture); - - CreateHiddenDependency(args.Holder(), args[1]); - } - return v8::Undefined(); -} - -CALLBACK_FUNC_DECL(MessagePortRemoveEventListener) -{ - INC_STATS("DOM.MessagePort.RemoveEventListener()"); - MessagePort* messagePort = V8Proxy::ToNativeObject<MessagePort>( - V8ClassIndex::MESSAGEPORT, args.Holder()); - - V8Proxy* proxy = V8Proxy::retrieve(messagePort->scriptExecutionContext()); - if (!proxy) - return v8::Undefined(); // probably leaked - - RefPtr<EventListener> listener = - proxy->FindObjectEventListener(args[1], false); - - if (listener) { - String type = ToWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - messagePort->removeEventListener(type, listener.get(), useCapture); - - RemoveHiddenDependency(args.Holder(), args[1]); - } - - return v8::Undefined(); -} - -} // namespace WebCore diff --git a/V8Binding/binding/V8NPObject.cpp b/V8Binding/binding/V8NPObject.cpp index 60e66a9..8d3a518 100644 --- a/V8Binding/binding/V8NPObject.cpp +++ b/V8Binding/binding/V8NPObject.cpp @@ -1,312 +1,315 @@ -// Copyright (c) 2008, 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. +/* +* Copyright (C) 2006, 2007, 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 "v8_custom.h" -#include "v8_helpers.h" #include "V8NPObject.h" -#include "V8NPUtils.h" -#include "NPV8Object.h" -#include "npruntime_priv.h" -#include "v8_proxy.h" -#include "dom_wrapper_map.h" + #include "HTMLPlugInElement.h" +#include "npruntime_priv.h" +#include "NPV8Object.h" +#include "V8CustomBinding.h" +#include "V8DOMMap.h" #include "V8HTMLAppletElement.h" #include "V8HTMLEmbedElement.h" #include "V8HTMLObjectElement.h" +#include "V8NPUtils.h" +#include "V8Proxy.h" +#include "v8_helpers.h" +#include "wtf/OwnArrayPtr.h" using namespace WebCore; enum InvokeFunctionType { INVOKE_METHOD = 1, - INVOKE_DEFAULT = 2 + INVOKE_CONSTRUCT = 2, + INVOKE_DEFAULT = 3 }; -// TODO(mbelshe): need comments. +// FIXME: need comments. // Params: holder could be HTMLEmbedElement or NPObject -static v8::Handle<v8::Value> NPObjectInvokeImpl(const v8::Arguments& args, InvokeFunctionType funcId) +static v8::Handle<v8::Value> npObjectInvokeImpl(const v8::Arguments& args, InvokeFunctionType functionId) { - NPObject* npobject; + NPObject* npObject; // These three types are subtypes of HTMLPlugInElement. - if (V8HTMLAppletElement::HasInstance(args.Holder()) || - V8HTMLEmbedElement::HasInstance(args.Holder()) || - V8HTMLObjectElement::HasInstance(args.Holder())) { + if (V8HTMLAppletElement::HasInstance(args.Holder()) || V8HTMLEmbedElement::HasInstance(args.Holder()) + || V8HTMLObjectElement::HasInstance(args.Holder())) { // The holder object is a subtype of HTMLPlugInElement. - HTMLPlugInElement* imp = V8Proxy::DOMWrapperToNode<HTMLPlugInElement>(args.Holder()); - ScriptInstance scriptInstance = imp->getInstance(); + HTMLPlugInElement* element = V8Proxy::DOMWrapperToNode<HTMLPlugInElement>(args.Holder()); + ScriptInstance scriptInstance = element->getInstance(); if (scriptInstance) - npobject = V8Proxy::ToNativeObject<NPObject>(V8ClassIndex::NPOBJECT, scriptInstance->instance()); + npObject = V8Proxy::ToNativeObject<NPObject>(V8ClassIndex::NPOBJECT, scriptInstance->instance()); else - npobject = NULL; + 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) { - V8Proxy::ThrowError(V8Proxy::REFERENCE_ERROR, "NPMethod called on non-NPObject"); - return v8::Undefined(); - } - npobject = V8Proxy::ToNativeObject<NPObject>(V8ClassIndex::NPOBJECT, args.Holder()); + if (args.Holder()->InternalFieldCount() != V8Custom::kNPObjectInternalFieldCount) + return throwError("NPMethod called on non-NPObject", V8Proxy::REFERENCE_ERROR); + + npObject = V8Proxy::ToNativeObject<NPObject>(V8ClassIndex::NPOBJECT, args.Holder()); } // Verify that our wrapper wasn't using a NPObject which // has already been deleted. - if (!npobject || !_NPN_IsAlive(npobject)) { - V8Proxy::ThrowError(V8Proxy::REFERENCE_ERROR, "NPObject deleted"); - return v8::Undefined(); - } + if (!npObject || !_NPN_IsAlive(npObject)) + return throwError("NPObject deleted", V8Proxy::REFERENCE_ERROR); - // wrap up parameters - int argc = args.Length(); - NPVariant* npArgs = new NPVariant[argc]; + // Wrap up parameters. + int numArgs = args.Length(); + OwnArrayPtr<NPVariant> npArgs(new NPVariant[numArgs]); - for (int i = 0; i < argc; i++) - convertV8ObjectToNPVariant(args[i], npobject, &npArgs[i]); + for (int i = 0; i < numArgs; i++) + convertV8ObjectToNPVariant(args[i], npObject, &npArgs[i]); NPVariant result; VOID_TO_NPVARIANT(result); - switch (funcId) { + switch (functionId) { case INVOKE_METHOD: - if (npobject->_class->invoke) { - v8::Handle<v8::String> function_name(v8::String::Cast(*args.Data())); - NPIdentifier ident = getStringIdentifier(function_name); - npobject->_class->invoke(npobject, ident, npArgs, argc, &result); + if (npObject->_class->invoke) { + v8::Handle<v8::String> functionName(v8::String::Cast(*args.Data())); + NPIdentifier identifier = getStringIdentifier(functionName); + npObject->_class->invoke(npObject, identifier, npArgs.get(), numArgs, &result); } break; + case INVOKE_CONSTRUCT: + if (npObject->_class->construct) + npObject->_class->construct(npObject, npArgs.get(), numArgs, &result); + break; case INVOKE_DEFAULT: - if (npobject->_class->invokeDefault) - npobject->_class->invokeDefault(npobject, npArgs, argc, &result); + if (npObject->_class->invokeDefault) + npObject->_class->invokeDefault(npObject, npArgs.get(), numArgs, &result); break; default: break; } - for (int i=0; i < argc; i++) + for (int i=0; i < numArgs; i++) NPN_ReleaseVariantValue(&npArgs[i]); - delete[] npArgs; - // unwrap return values - v8::Handle<v8::Value> rv = convertNPVariantToV8Object(&result, npobject); + // Unwrap return values. + v8::Handle<v8::Value> returnValue = convertNPVariantToV8Object(&result, npObject); NPN_ReleaseVariantValue(&result); - return rv; + return returnValue; } -v8::Handle<v8::Value> NPObjectMethodHandler(const v8::Arguments& args) +v8::Handle<v8::Value> npObjectMethodHandler(const v8::Arguments& args) { - return NPObjectInvokeImpl(args, INVOKE_METHOD); + return npObjectInvokeImpl(args, INVOKE_METHOD); } -v8::Handle<v8::Value> NPObjectInvokeDefaultHandler(const v8::Arguments& args) +v8::Handle<v8::Value> npObjectInvokeDefaultHandler(const v8::Arguments& args) { - return NPObjectInvokeImpl(args, INVOKE_DEFAULT); + if (args.IsConstructCall()) + return npObjectInvokeImpl(args, INVOKE_CONSTRUCT); + else + return npObjectInvokeImpl(args, INVOKE_DEFAULT); } -static void WeakTemplateCallback(v8::Persistent<v8::Value> obj, void* param); +static void weakTemplateCallback(v8::Persistent<v8::Value>, void* parameter); // NPIdentifier is PrivateIdentifier*. -static WeakReferenceMap<PrivateIdentifier, v8::FunctionTemplate> \ - static_template_map(&WeakTemplateCallback); +static WeakReferenceMap<PrivateIdentifier, v8::FunctionTemplate> staticTemplateMap(&weakTemplateCallback); -static void WeakTemplateCallback(v8::Persistent<v8::Value> obj, void* param) +static void weakTemplateCallback(v8::Persistent<v8::Value> object, void* parameter) { - PrivateIdentifier* iden = static_cast<PrivateIdentifier*>(param); - ASSERT(iden != NULL); - ASSERT(static_template_map.contains(iden)); + PrivateIdentifier* identifier = static_cast<PrivateIdentifier*>(parameter); + ASSERT(identifier); + ASSERT(staticTemplateMap.contains(identifier)); - static_template_map.forget(iden); + staticTemplateMap.forget(identifier); } -static v8::Handle<v8::Value> NPObjectGetProperty(v8::Local<v8::Object> self, - NPIdentifier ident, +static v8::Handle<v8::Value> npObjectGetProperty(v8::Local<v8::Object> self, + NPIdentifier identifier, v8::Local<v8::Value> key) { - NPObject* npobject = V8Proxy::ToNativeObject<NPObject>(V8ClassIndex::NPOBJECT, self); + NPObject* npObject = V8Proxy::ToNativeObject<NPObject>(V8ClassIndex::NPOBJECT, self); // Verify that our wrapper wasn't using a NPObject which // has already been deleted. - if (!npobject || !_NPN_IsAlive(npobject)) { - V8Proxy::ThrowError(V8Proxy::REFERENCE_ERROR, "NPObject deleted"); - return v8::Handle<v8::Value>(); - } + if (!npObject || !_NPN_IsAlive(npObject)) + return throwError("NPObject deleted", V8Proxy::REFERENCE_ERROR); + - if (npobject->_class->hasProperty && - npobject->_class->hasProperty(npobject, ident) && - npobject->_class->getProperty) { + if (npObject->_class->hasProperty && npObject->_class->hasProperty(npObject, identifier) + && npObject->_class->getProperty) { NPVariant result; VOID_TO_NPVARIANT(result); - if (!npobject->_class->getProperty(npobject, ident, &result)) + if (!npObject->_class->getProperty(npObject, identifier, &result)) return v8::Handle<v8::Value>(); - v8::Handle<v8::Value> rv = convertNPVariantToV8Object(&result, npobject); + v8::Handle<v8::Value> returnValue = convertNPVariantToV8Object(&result, npObject); NPN_ReleaseVariantValue(&result); - return rv; - } else if (key->IsString() && npobject->_class->hasMethod && npobject->_class->hasMethod(npobject, ident)) { - PrivateIdentifier* id = static_cast<PrivateIdentifier*>(ident); - v8::Persistent<v8::FunctionTemplate> desc = static_template_map.get(id); + return returnValue; + + } else if (key->IsString() && npObject->_class->hasMethod && npObject->_class->hasMethod(npObject, identifier)) { + PrivateIdentifier* id = static_cast<PrivateIdentifier*>(identifier); + v8::Persistent<v8::FunctionTemplate> functionTemplate = staticTemplateMap.get(id); // Cache templates using identifier as the key. - if (desc.IsEmpty()) { - // Create a new template + if (functionTemplate.IsEmpty()) { + // Create a new template. v8::Local<v8::FunctionTemplate> temp = v8::FunctionTemplate::New(); - temp->SetCallHandler(NPObjectMethodHandler, key); - desc = v8::Persistent<v8::FunctionTemplate>::New(temp); - static_template_map.set(id, desc); + temp->SetCallHandler(npObjectMethodHandler, key); + functionTemplate = v8::Persistent<v8::FunctionTemplate>::New(temp); + staticTemplateMap.set(id, functionTemplate); } // FunctionTemplate caches function for each context. - v8::Local<v8::Function> func = desc->GetFunction(); - func->SetName(v8::Handle<v8::String>::Cast(key)); - return func; + v8::Local<v8::Function> v8Function = functionTemplate->GetFunction(); + v8Function->SetName(v8::Handle<v8::String>::Cast(key)); + return v8Function; } return v8::Handle<v8::Value>(); } -v8::Handle<v8::Value> NPObjectNamedPropertyGetter(v8::Local<v8::String> name, +v8::Handle<v8::Value> npObjectNamedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { - NPIdentifier ident = getStringIdentifier(name); - return NPObjectGetProperty(info.Holder(), ident, name); + NPIdentifier identifier = getStringIdentifier(name); + return npObjectGetProperty(info.Holder(), identifier, name); } -v8::Handle<v8::Value> NPObjectIndexedPropertyGetter(uint32_t index, +v8::Handle<v8::Value> npObjectIndexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info) { - NPIdentifier ident = NPN_GetIntIdentifier(index); - return NPObjectGetProperty(info.Holder(), ident, v8::Number::New(index)); + NPIdentifier identifier = NPN_GetIntIdentifier(index); + return npObjectGetProperty(info.Holder(), identifier, v8::Number::New(index)); } -v8::Handle<v8::Value> NPObjectGetNamedProperty(v8::Local<v8::Object> self, +v8::Handle<v8::Value> npObjectGetNamedProperty(v8::Local<v8::Object> self, v8::Local<v8::String> name) { - NPIdentifier ident = getStringIdentifier(name); - return NPObjectGetProperty(self, ident, name); + NPIdentifier identifier = getStringIdentifier(name); + return npObjectGetProperty(self, identifier, name); } -v8::Handle<v8::Value> NPObjectGetIndexedProperty(v8::Local<v8::Object> self, +v8::Handle<v8::Value> npObjectGetIndexedProperty(v8::Local<v8::Object> self, uint32_t index) { - NPIdentifier ident = NPN_GetIntIdentifier(index); - return NPObjectGetProperty(self, ident, v8::Number::New(index)); + NPIdentifier identifier = NPN_GetIntIdentifier(index); + return npObjectGetProperty(self, identifier, v8::Number::New(index)); } -static v8::Handle<v8::Value> NPObjectSetProperty(v8::Local<v8::Object> self, - NPIdentifier ident, +static v8::Handle<v8::Value> npObjectSetProperty(v8::Local<v8::Object> self, + NPIdentifier identifier, v8::Local<v8::Value> value) { - NPObject* npobject = V8Proxy::ToNativeObject<NPObject>(V8ClassIndex::NPOBJECT, self); + NPObject* npObject = V8Proxy::ToNativeObject<NPObject>(V8ClassIndex::NPOBJECT, self); // Verify that our wrapper wasn't using a NPObject which // has already been deleted. - if (!npobject || !_NPN_IsAlive(npobject)) { - V8Proxy::ThrowError(V8Proxy::REFERENCE_ERROR, "NPObject deleted"); - return value; // intercepted, but an exception was thrown + if (!npObject || !_NPN_IsAlive(npObject)) { + throwError("NPObject deleted", V8Proxy::REFERENCE_ERROR); + return value; // Intercepted, but an exception was thrown. } - if (npobject->_class->hasProperty && - npobject->_class->hasProperty(npobject, ident) && - npobject->_class->setProperty) { - - NPVariant npvalue; - VOID_TO_NPVARIANT(npvalue); - convertV8ObjectToNPVariant(value, npobject, &npvalue); - bool succ = npobject->_class->setProperty(npobject, ident, &npvalue); - NPN_ReleaseVariantValue(&npvalue); - if (succ) - return value; // intercept the call + if (npObject->_class->hasProperty && npObject->_class->hasProperty(npObject, identifier) + && npObject->_class->setProperty) { + + NPVariant npValue; + VOID_TO_NPVARIANT(npValue); + convertV8ObjectToNPVariant(value, npObject, &npValue); + bool success = npObject->_class->setProperty(npObject, identifier, &npValue); + NPN_ReleaseVariantValue(&npValue); + if (success) + return value; // Intercept the call. } - return v8::Local<v8::Value>(); // do not intercept the call + return v8::Local<v8::Value>(); // Do not intercept the call. } -v8::Handle<v8::Value> NPObjectNamedPropertySetter(v8::Local<v8::String> name, +v8::Handle<v8::Value> npObjectNamedPropertySetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { - NPIdentifier ident = getStringIdentifier(name); - return NPObjectSetProperty(info.Holder(), ident, value); + NPIdentifier identifier = getStringIdentifier(name); + return npObjectSetProperty(info.Holder(), identifier, value); } -v8::Handle<v8::Value> NPObjectIndexedPropertySetter(uint32_t index, +v8::Handle<v8::Value> npObjectIndexedPropertySetter(uint32_t index, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { - NPIdentifier ident = NPN_GetIntIdentifier(index); - return NPObjectSetProperty(info.Holder(), ident, value); + NPIdentifier identifier = NPN_GetIntIdentifier(index); + return npObjectSetProperty(info.Holder(), identifier, value); } -v8::Handle<v8::Value> NPObjectSetNamedProperty(v8::Local<v8::Object> self, +v8::Handle<v8::Value> npObjectSetNamedProperty(v8::Local<v8::Object> self, v8::Local<v8::String> name, v8::Local<v8::Value> value) { - NPIdentifier ident = getStringIdentifier(name); - return NPObjectSetProperty(self, ident, value); + NPIdentifier identifier = getStringIdentifier(name); + return npObjectSetProperty(self, identifier, value); } -v8::Handle<v8::Value> NPObjectSetIndexedProperty(v8::Local<v8::Object> self, +v8::Handle<v8::Value> npObjectSetIndexedProperty(v8::Local<v8::Object> self, uint32_t index, v8::Local<v8::Value> value) { - NPIdentifier ident = NPN_GetIntIdentifier(index); - return NPObjectSetProperty(self, ident, value); + NPIdentifier identifier = NPN_GetIntIdentifier(index); + return npObjectSetProperty(self, identifier, value); } -static void WeakNPObjectCallback(v8::Persistent<v8::Value> obj, void* param); +static void weakNPObjectCallback(v8::Persistent<v8::Value>, void* parameter); -static DOMWrapperMap<NPObject> staticNpobjectMap(&WeakNPObjectCallback); +static DOMWrapperMap<NPObject> staticNPObjectMap(&weakNPObjectCallback); -static void WeakNPObjectCallback(v8::Persistent<v8::Value> obj, void* param) +static void weakNPObjectCallback(v8::Persistent<v8::Value> object, void* parameter) { - NPObject* npobject = static_cast<NPObject*>(param); - ASSERT(staticNpobjectMap.contains(npobject)); - ASSERT(npobject != NULL); + NPObject* npObject = static_cast<NPObject*>(parameter); + ASSERT(staticNPObjectMap.contains(npObject)); + ASSERT(npObject); // Must remove from our map before calling NPN_ReleaseObject(). // NPN_ReleaseObject can call ForgetV8ObjectForNPObject, which // uses the table as well. - staticNpobjectMap.forget(npobject); + staticNPObjectMap.forget(npObject); - if (_NPN_IsAlive(npobject)) - NPN_ReleaseObject(npobject); + if (_NPN_IsAlive(npObject)) + NPN_ReleaseObject(npObject); } -v8::Local<v8::Object> CreateV8ObjectForNPObject(NPObject* object, NPObject* root) +v8::Local<v8::Object> createV8ObjectForNPObject(NPObject* object, NPObject* root) { static v8::Persistent<v8::FunctionTemplate> npObjectDesc; @@ -314,15 +317,15 @@ v8::Local<v8::Object> CreateV8ObjectForNPObject(NPObject* object, NPObject* root // If this is a v8 object, just return it. if (object->_class == npScriptObjectClass) { - V8NPObject* v8npobject = reinterpret_cast<V8NPObject*>(object); - return v8::Local<v8::Object>::New(v8npobject->v8Object); + V8NPObject* v8NPObject = reinterpret_cast<V8NPObject*>(object); + return v8::Local<v8::Object>::New(v8NPObject->v8Object); } // If we've already wrapped this object, just return it. - if (staticNpobjectMap.contains(object)) - return v8::Local<v8::Object>::New(staticNpobjectMap.get(object)); + if (staticNPObjectMap.contains(object)) + return v8::Local<v8::Object>::New(staticNPObjectMap.get(object)); - // TODO: we should create a Wrapper type as a subclass of JSObject. + // FIXME: we should create a Wrapper type as a subclass of JSObject. // It has two internal fields, field 0 is the wrapped pointer, // and field 1 is the type. There should be an api function that // returns unused type id. @@ -330,40 +333,40 @@ v8::Local<v8::Object> CreateV8ObjectForNPObject(NPObject* object, NPObject* root if (npObjectDesc.IsEmpty()) { npObjectDesc = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New()); npObjectDesc->InstanceTemplate()->SetInternalFieldCount(V8Custom::kNPObjectInternalFieldCount); - npObjectDesc->InstanceTemplate()->SetNamedPropertyHandler(NPObjectNamedPropertyGetter, NPObjectNamedPropertySetter); - npObjectDesc->InstanceTemplate()->SetIndexedPropertyHandler(NPObjectIndexedPropertyGetter, NPObjectIndexedPropertySetter); - npObjectDesc->InstanceTemplate()->SetCallAsFunctionHandler(NPObjectInvokeDefaultHandler); + npObjectDesc->InstanceTemplate()->SetNamedPropertyHandler(npObjectNamedPropertyGetter, npObjectNamedPropertySetter); + npObjectDesc->InstanceTemplate()->SetIndexedPropertyHandler(npObjectIndexedPropertyGetter, npObjectIndexedPropertySetter); + npObjectDesc->InstanceTemplate()->SetCallAsFunctionHandler(npObjectInvokeDefaultHandler); } - v8::Handle<v8::Function> func = npObjectDesc->GetFunction(); - v8::Local<v8::Object> value = SafeAllocation::NewInstance(func); + v8::Handle<v8::Function> v8Function = npObjectDesc->GetFunction(); + v8::Local<v8::Object> value = SafeAllocation::NewInstance(v8Function); - // If we were unable to allocate the instance we avoid wrapping + // If we were unable to allocate the instance, we avoid wrapping // and registering the NP object. if (value.IsEmpty()) return value; WrapNPObject(value, object); - // KJS retains the object as part of its wrapper (see Bindings::CInstance) + // KJS retains the object as part of its wrapper (see Bindings::CInstance). NPN_RetainObject(object); _NPN_RegisterObject(object, root); // Maintain a weak pointer for v8 so we can cleanup the object. v8::Persistent<v8::Object> weakRef = v8::Persistent<v8::Object>::New(value); - staticNpobjectMap.set(object, weakRef); + staticNPObjectMap.set(object, weakRef); return value; } -void ForgetV8ObjectForNPObject(NPObject* object) +void forgetV8ObjectForNPObject(NPObject* object) { - if (staticNpobjectMap.contains(object)) { + if (staticNPObjectMap.contains(object)) { v8::HandleScope scope; - v8::Persistent<v8::Object> handle(staticNpobjectMap.get(object)); - WebCore::V8Proxy::SetDOMWrapper(handle, WebCore::V8ClassIndex::NPOBJECT, NULL); - staticNpobjectMap.forget(object); + v8::Persistent<v8::Object> handle(staticNPObjectMap.get(object)); + WebCore::V8Proxy::SetDOMWrapper(handle, WebCore::V8ClassIndex::NPOBJECT, 0); + staticNPObjectMap.forget(object); NPN_ReleaseObject(object); } } diff --git a/V8Binding/binding/V8NPObject.h b/V8Binding/binding/V8NPObject.h index 04cbff1..e18ed3d 100644 --- a/V8Binding/binding/V8NPObject.h +++ b/V8Binding/binding/V8NPObject.h @@ -1,9 +1,35 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. +/* + * Copyright (C) 2006, 2007, 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. + */ -#ifndef v8_npobject_h -#define v8_npobject_h +#ifndef V8NPObject_h +#define V8NPObject_h #include <v8.h> #if PLATFORM(CHROMIUM) @@ -12,31 +38,30 @@ #include "bridge/npruntime.h" // use WebCore version #endif +// FIXME: Remove these #defines when upstreamed. They are needed to compile +// some currently upstreamed files which will need to be modified when this +// file is upstreamed. +#define NPObjectGetNamedProperty npObjectGetNamedProperty +#define NPObjectSetNamedProperty npObjectSetNamedProperty +#define NPObjectInvokeDefaultHandler npObjectInvokeDefaultHandler +#define NPObjectGetIndexedProperty npObjectGetIndexedProperty +#define NPObjectSetIndexedProperty npObjectSetIndexedProperty +#define CreateV8ObjectForNPObject createV8ObjectForNPObject + // These functions can be replaced by normal JS operation. // Getters -v8::Handle<v8::Value> NPObjectNamedPropertyGetter(v8::Local<v8::String> name, - const v8::AccessorInfo& info); -v8::Handle<v8::Value> NPObjectIndexedPropertyGetter(uint32_t index, - const v8::AccessorInfo& info); -v8::Handle<v8::Value> NPObjectGetNamedProperty(v8::Local<v8::Object> self, - v8::Local<v8::String> name); -v8::Handle<v8::Value> NPObjectGetIndexedProperty(v8::Local<v8::Object> self, - uint32_t index); +v8::Handle<v8::Value> npObjectNamedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo&); +v8::Handle<v8::Value> npObjectIndexedPropertyGetter(uint32_t index, const v8::AccessorInfo&); +v8::Handle<v8::Value> npObjectGetNamedProperty(v8::Local<v8::Object> self, v8::Local<v8::String> name); +v8::Handle<v8::Value> npObjectGetIndexedProperty(v8::Local<v8::Object> self, uint32_t index); // Setters -v8::Handle<v8::Value> NPObjectNamedPropertySetter(v8::Local<v8::String> name, - v8::Local<v8::Value> value, - const v8::AccessorInfo& info); -v8::Handle<v8::Value> NPObjectIndexedPropertySetter(uint32_t index, - const v8::AccessorInfo& info); -v8::Handle<v8::Value> NPObjectSetNamedProperty(v8::Local<v8::Object> self, - v8::Local<v8::String> name, - v8::Local<v8::Value> value); -v8::Handle<v8::Value> NPObjectSetIndexedProperty(v8::Local<v8::Object> self, - uint32_t index, - v8::Local<v8::Value> value); - -v8::Handle<v8::Value> NPObjectInvokeDefaultHandler(const v8::Arguments& args); +v8::Handle<v8::Value> npObjectNamedPropertySetter(v8::Local<v8::String> name, v8::Local<v8::Value>, const v8::AccessorInfo&); +v8::Handle<v8::Value> npObjectIndexedPropertySetter(uint32_t index, const v8::AccessorInfo&); +v8::Handle<v8::Value> npObjectSetNamedProperty(v8::Local<v8::Object> self, v8::Local<v8::String> name, v8::Local<v8::Value>); +v8::Handle<v8::Value> npObjectSetIndexedProperty(v8::Local<v8::Object> self, uint32_t index, v8::Local<v8::Value>); + +v8::Handle<v8::Value> npObjectInvokeDefaultHandler(const v8::Arguments&); // Get a wrapper for a NPObject. // If the object is already wrapped, the pre-existing wrapper @@ -44,14 +69,14 @@ v8::Handle<v8::Value> NPObjectInvokeDefaultHandler(const v8::Arguments& args); // If the object is not wrapped, wrap it, and give V8 a weak // reference to the wrapper which will cleanup when there are // no more JS references to the object. -v8::Local<v8::Object> CreateV8ObjectForNPObject(NPObject* object, NPObject *root); +v8::Local<v8::Object> createV8ObjectForNPObject(NPObject*, NPObject* root); // Tell V8 to forcibly remove an object. // This is used at plugin teardown so that the caller can -// aggressively unload the plugin library. After calling this +// aggressively unload the plugin library. After calling this // function, the persistent handle to the wrapper will be // gone, and the wrapped NPObject will be removed so that // it cannot be referred to. -void ForgetV8ObjectForNPObject(NPObject*object); +void forgetV8ObjectForNPObject(NPObject*); -#endif // v8_npobject_h +#endif // V8NPObject_h diff --git a/V8Binding/binding/V8NPUtils.cpp b/V8Binding/binding/V8NPUtils.cpp index 04e6ede..3a68288 100644 --- a/V8Binding/binding/V8NPUtils.cpp +++ b/V8Binding/binding/V8NPUtils.cpp @@ -99,7 +99,7 @@ v8::Handle<v8::Value> convertNPVariantToV8Object(const NPVariant* variant, NPObj NPObject* obj = NPVARIANT_TO_OBJECT(*variant); if (obj->_class == npScriptObjectClass) return reinterpret_cast<V8NPObject*>(obj)->v8Object; - return CreateV8ObjectForNPObject(obj, npobject); + return createV8ObjectForNPObject(obj, npobject); } return v8::Undefined(); } diff --git a/V8Binding/binding/V8SVGPODTypeWrapper.h b/V8Binding/binding/V8SVGPODTypeWrapper.h index 79553c2..0fb1fb8 100644 --- a/V8Binding/binding/V8SVGPODTypeWrapper.h +++ b/V8Binding/binding/V8SVGPODTypeWrapper.h @@ -36,6 +36,7 @@ #include <wtf/Assertions.h> #include <wtf/RefCounted.h> #include <wtf/HashMap.h> +#include "v8_proxy.h" namespace WebCore { @@ -357,6 +358,29 @@ public: }; +class V8SVGPODTypeUtil { +public: + template <class P> + static P ToSVGPODType(V8ClassIndex::V8WrapperType type, + v8::Handle<v8::Value> object, bool& ok); +}; + + +template <class P> +P V8SVGPODTypeUtil::ToSVGPODType(V8ClassIndex::V8WrapperType type, + v8::Handle<v8::Value> object, + bool& ok) { + void *wrapper = V8Proxy::ToSVGPODTypeImpl(type, object); + if (wrapper == NULL) { + ok = false; + return P(); + } else { + ok = true; + return *static_cast<V8SVGPODTypeWrapper<P>*>(wrapper); + } +} + + } // namespace WebCore #endif // ENABLE(SVG) diff --git a/V8Binding/binding/V8Utilities.cpp b/V8Binding/binding/V8Utilities.cpp deleted file mode 100644 index 8853506..0000000 --- a/V8Binding/binding/V8Utilities.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2008, 2009 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "V8Utilities.h" - -#include <v8.h> - -#include "V8CustomBinding.h" -#include "V8Proxy.h" - -#include <wtf/Assertions.h> -#include "Frame.h" - -namespace WebCore { - -// Use an array to hold dependents. It works like a ref-counted scheme. -// A value can be added more than once to the DOM object. -void createHiddenDependency(v8::Local<v8::Object> object, v8::Local<v8::Value> value, int cacheIndex) -{ - v8::Local<v8::Value> cache = object->GetInternalField(cacheIndex); - if (cache->IsNull() || cache->IsUndefined()) { - cache = v8::Array::New(); - object->SetInternalField(cacheIndex, cache); - } - - v8::Local<v8::Array> cacheArray = v8::Local<v8::Array>::Cast(cache); - cacheArray->Set(v8::Integer::New(cacheArray->Length()), value); -} - -void removeHiddenDependency(v8::Local<v8::Object> object, v8::Local<v8::Value> value, int cacheIndex) -{ - v8::Local<v8::Value> cache = object->GetInternalField(cacheIndex); - ASSERT(cache->IsArray()); - v8::Local<v8::Array> cacheArray = v8::Local<v8::Array>::Cast(cache); - for (int i = cacheArray->Length() - 1; i >= 0; --i) { - v8::Local<v8::Value> cached = cacheArray->Get(v8::Integer::New(i)); - if (cached->StrictEquals(value)) { - cacheArray->Delete(i); - return; - } - } - - // We should only get here if we try to remove an event listener that was never added. - ASSERT_NOT_REACHED(); -} - -#if PLATFORM(ANDROID) - // The functions below are not needed on Android. -#else -bool processingUserGesture() -{ - Frame* frame = V8Proxy::retrieveFrameForEnteredContext(); - return frame && frame->script()->processingUserGesture(); -} - -bool shouldAllowNavigation(Frame* frame) -{ - Frame* callingFrame = V8Proxy::retrieveFrameForCallingContext(); - return callingFrame && callingFrame->loader()->shouldAllowNavigation(frame); -} - -KURL completeURL(const String& relativeURL) -{ - // For histoical reasons, we need to complete the URL using the dynamic frame. - Frame* frame = V8Proxy::retrieveFrameForEnteredContext(); - if (!frame) - return KURL(); - return frame->loader()->completeURL(relativeURL); -} - -void navigateIfAllowed(Frame* frame, const KURL& url, bool lockHistory, bool lockBackForwardList) -{ - Frame* callingFrame = V8Proxy::retrieveFrameForCallingContext(); - if (!callingFrame) - return; - - if (!protocolIsJavaScript(url) || ScriptController::isSafeScript(frame)) - frame->loader()->scheduleLocationChange(url.string(), callingFrame->loader()->outgoingReferrer(), lockHistory, lockBackForwardList, processingUserGesture()); -} -#endif // PLATFORM(ANDROID) - -} // namespace WebCore diff --git a/V8Binding/binding/V8Utilities.h b/V8Binding/binding/V8Utilities.h deleted file mode 100644 index f4346f6..0000000 --- a/V8Binding/binding/V8Utilities.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 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. - */ - -#ifndef V8Utilities_h -#define V8Utilities_h - -// FIXME: Remove once chromium dependencies on v8_utility.h are removed. -#define V8UTILITIES_DEFINED 1 - -#include <v8.h> - -namespace WebCore { - - class Frame; - class KURL; - class String; - - // Use an array to hold dependents. It works like a ref-counted scheme. A value can be added more than once to the DOM object. - void createHiddenDependency(v8::Local<v8::Object>, v8::Local<v8::Value>, int cacheIndex); - void removeHiddenDependency(v8::Local<v8::Object>, v8::Local<v8::Value>, int cacheIndex); - -#if PLATFORM(ANDROID) - // The functions below are not needed (yet) on Android. -#else - bool processingUserGesture(); - bool shouldAllowNavigation(Frame*); - KURL completeURL(const String& relativeURL); - void navigateIfAllowed(Frame*, const KURL&, bool lockHistory, bool lockBackForwardList); -#endif // PLATFORM(ANDROID) - - class AllowAllocation { - public: - inline AllowAllocation() - { - m_previous = m_current; - m_current = true; - } - - inline ~AllowAllocation() - { - m_current = m_previous; - } - - static bool m_current; - - private: - bool m_previous; - }; - - class SafeAllocation { - public: - static inline v8::Local<v8::Object> newInstance(v8::Handle<v8::Function>); - static inline v8::Local<v8::Object> newInstance(v8::Handle<v8::ObjectTemplate>); - static inline v8::Local<v8::Object> newInstance(v8::Handle<v8::Function>, int argc, v8::Handle<v8::Value> argv[]); - - // FIXME: These NewInstance functions are here to ease upstreaming. Remove along with V8UTILITIES_DEFINED once chromium dependencies on v8_utility.h are removed. - static inline v8::Local<v8::Object> NewInstance(v8::Handle<v8::Function>); - static inline v8::Local<v8::Object> NewInstance(v8::Handle<v8::ObjectTemplate>); - static inline v8::Local<v8::Object> NewInstance(v8::Handle<v8::Function>, int argc, v8::Handle<v8::Value> argv[]); - }; - - v8::Local<v8::Object> SafeAllocation::newInstance(v8::Handle<v8::Function> function) - { - if (function.IsEmpty()) - return v8::Local<v8::Object>(); - AllowAllocation allow; - return function->NewInstance(); - } - - v8::Local<v8::Object> SafeAllocation::newInstance(v8::Handle<v8::ObjectTemplate> objectTemplate) - { - if (objectTemplate.IsEmpty()) - return v8::Local<v8::Object>(); - AllowAllocation allow; - return objectTemplate->NewInstance(); - } - - v8::Local<v8::Object> SafeAllocation::newInstance(v8::Handle<v8::Function> function, int argc, v8::Handle<v8::Value> argv[]) - { - if (function.IsEmpty()) - return v8::Local<v8::Object>(); - AllowAllocation allow; - return function->NewInstance(argc, argv); - } - - // FIXME: These NewInstance functions are here to ease upstreaming. Remove along with V8UTILITIES_DEFINED once chromium dependencies on v8_utility.h are removed. - v8::Local<v8::Object> SafeAllocation::NewInstance(v8::Handle<v8::Function> function) - { - return newInstance(function); - } - - v8::Local<v8::Object> SafeAllocation::NewInstance(v8::Handle<v8::ObjectTemplate> objectTemplate) - { - return newInstance(objectTemplate); - } - - v8::Local<v8::Object> SafeAllocation::NewInstance(v8::Handle<v8::Function> function, int argc, v8::Handle<v8::Value> argv[]) - { - return newInstance(function, argc, argv); - } - -} // namespace WebCore - -#endif // V8Utilities_h diff --git a/V8Binding/binding/V8WorkerContextCustom.cpp b/V8Binding/binding/V8WorkerContextCustom.cpp deleted file mode 100644 index e646bb5..0000000 --- a/V8Binding/binding/V8WorkerContextCustom.cpp +++ /dev/null @@ -1,230 +0,0 @@ -// Copyright (c) 2009, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "config.h" - -#if ENABLE(WORKERS) - -#include "v8_binding.h" -#include "v8_custom.h" -#include "v8_proxy.h" -#include "WorkerContextExecutionProxy.h" - -#include "ExceptionCode.h" -#include "MessagePort.h" -#include "NotImplemented.h" -#include "V8Document.h" -#include "V8HTMLDocument.h" -#include "V8WorkerContextEventListener.h" -#include "WorkerContext.h" - -namespace WebCore { - -// TODO(mbelshe) - merge these with XHR's CreateHiddenXHRDependency - -// Use an array to hold dependents. It works like a ref-counted scheme. -// A value can be added more than once to the xhr object. -static void CreateHiddenDependency(v8::Local<v8::Object> object, - v8::Local<v8::Value> value) { - ASSERT(V8Proxy::GetDOMWrapperType(object) == V8ClassIndex::WORKERCONTEXT); - v8::Local<v8::Value> cache = - object->GetInternalField(V8Custom::kWorkerContextRequestCacheIndex); - if (cache->IsNull() || cache->IsUndefined()) { - cache = v8::Array::New(); - object->SetInternalField(V8Custom::kWorkerContextRequestCacheIndex, cache); - } - - v8::Local<v8::Array> cache_array = v8::Local<v8::Array>::Cast(cache); - cache_array->Set(v8::Integer::New(cache_array->Length()), value); -} - -static void RemoveHiddenDependency(v8::Local<v8::Object> object, - v8::Local<v8::Value> value) { - ASSERT(V8Proxy::GetDOMWrapperType(object) == V8ClassIndex::WORKERCONTEXT); - v8::Local<v8::Value> cache = - object->GetInternalField(V8Custom::kWorkerContextRequestCacheIndex); - ASSERT(cache->IsArray()); - v8::Local<v8::Array> cache_array = v8::Local<v8::Array>::Cast(cache); - for (int i = cache_array->Length() - 1; i >= 0; i--) { - v8::Local<v8::Value> cached = cache_array->Get(v8::Integer::New(i)); - if (cached->StrictEquals(value)) { - cache_array->Delete(i); - return; - } - } - - // We should only get here if we try to remove an event listener that was - // never added. -} - -ACCESSOR_GETTER(WorkerContextSelf) { - INC_STATS(L"DOM.WorkerContext.self._get"); - WorkerContext* imp = V8Proxy::ToNativeObject<WorkerContext>( - V8ClassIndex::WORKERCONTEXT, info.Holder()); - return WorkerContextExecutionProxy::WorkerContextToV8Object(imp); -} - -ACCESSOR_GETTER(WorkerContextOnmessage) { - INC_STATS(L"DOM.WorkerContext.onmessage._get"); - WorkerContext* imp = V8Proxy::ToNativeObject<WorkerContext>( - V8ClassIndex::WORKERCONTEXT, info.Holder()); - if (imp->onmessage()) { - V8WorkerContextEventListener* listener = - static_cast<V8WorkerContextEventListener*>(imp->onmessage()); - v8::Local<v8::Object> v8_listener = listener->getListenerObject(); - return v8_listener; - } - return v8::Undefined(); -} - -ACCESSOR_SETTER(WorkerContextOnmessage) { - INC_STATS(L"DOM.WorkerContext.onmessage._set"); - WorkerContext* imp = V8Proxy::ToNativeObject<WorkerContext>( - V8ClassIndex::WORKERCONTEXT, info.Holder()); - V8WorkerContextEventListener* old_listener = - static_cast<V8WorkerContextEventListener*>(imp->onmessage()); - if (value->IsNull()) { - if (imp->onmessage()) { - v8::Local<v8::Object> old_v8_listener = old_listener->getListenerObject(); - RemoveHiddenDependency(info.Holder(), old_v8_listener); - } - - // Clear the listener - imp->setOnmessage(0); - - } else { - RefPtr<V8EventListener> listener = - imp->script()->proxy()->FindOrCreateEventListener( - v8::Local<v8::Object>::Cast(value), false, false); - if (listener) { - if (old_listener) { - v8::Local<v8::Object> old_v8_listener = - old_listener->getListenerObject(); - RemoveHiddenDependency(info.Holder(), old_v8_listener); - } - - imp->setOnmessage(listener); - CreateHiddenDependency(info.Holder(), value); - } - } -} - -v8::Handle<v8::Value> SetTimeoutOrInterval(const v8::Arguments& args, - bool singleShot) { - WorkerContext* imp = V8Proxy::ToNativeObject<WorkerContext>( - V8ClassIndex::WORKERCONTEXT, args.Holder()); - - int delay = ToInt32(args[1]); - - notImplemented(); - - return v8::Undefined(); -} - -v8::Handle<v8::Value> ClearTimeoutOrInterval(const v8::Arguments& args) { - WorkerContext* imp = V8Proxy::ToNativeObject<WorkerContext>( - V8ClassIndex::WORKERCONTEXT, args.Holder()); - - bool ok = false; - int tid = ToInt32(args[0], ok); - if (ok) { - imp->removeTimeout(tid); - } - - return v8::Undefined(); -} - -CALLBACK_FUNC_DECL(WorkerContextImportScripts) { - INC_STATS(L"DOM.WorkerContext.importScripts()"); - notImplemented(); - return v8::Undefined(); -} - -CALLBACK_FUNC_DECL(WorkerContextSetTimeout) { - INC_STATS(L"DOM.WorkerContext.setTimeout()"); - return SetTimeoutOrInterval(args, true); -} - -CALLBACK_FUNC_DECL(WorkerContextClearTimeout) { - INC_STATS(L"DOM.WorkerContext.clearTimeout()"); - return ClearTimeoutOrInterval(args); -} - -CALLBACK_FUNC_DECL(WorkerContextSetInterval) { - INC_STATS(L"DOM.WorkerContext.setInterval()"); - return SetTimeoutOrInterval(args, false); -} - -CALLBACK_FUNC_DECL(WorkerContextClearInterval) { - INC_STATS(L"DOM.WorkerContext.clearInterval()"); - return ClearTimeoutOrInterval(args); -} - -CALLBACK_FUNC_DECL(WorkerContextAddEventListener) { - INC_STATS(L"DOM.WorkerContext.addEventListener()"); - WorkerContext* imp = V8Proxy::ToNativeObject<WorkerContext>( - V8ClassIndex::WORKERCONTEXT, args.Holder()); - - RefPtr<V8EventListener> listener = - imp->script()->proxy()->FindOrCreateEventListener( - v8::Local<v8::Object>::Cast(args[1]), false, false); - - if (listener) { - String type = ToWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - imp->addEventListener(type, listener, useCapture); - - CreateHiddenDependency(args.Holder(), args[1]); - } - return v8::Undefined(); -} - -CALLBACK_FUNC_DECL(WorkerContextRemoveEventListener) { - INC_STATS(L"DOM.WorkerContext.removeEventListener()"); - WorkerContext* imp = V8Proxy::ToNativeObject<WorkerContext>( - V8ClassIndex::WORKERCONTEXT, args.Holder()); - WorkerContextExecutionProxy* proxy = imp->script()->proxy(); - - RefPtr<V8EventListener> listener = proxy->FindOrCreateEventListener( - v8::Local<v8::Object>::Cast(args[1]), false, true); - - if (listener) { - String type = ToWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - imp->removeEventListener(type, listener.get(), useCapture); - - RemoveHiddenDependency(args.Holder(), args[1]); - } - - return v8::Undefined(); -} - -} // namespace WebCore - -#endif // ENABLE(WORKERS) diff --git a/V8Binding/binding/V8WorkerCustom.cpp b/V8Binding/binding/V8WorkerCustom.cpp deleted file mode 100644 index 1f7e5fe..0000000 --- a/V8Binding/binding/V8WorkerCustom.cpp +++ /dev/null @@ -1,282 +0,0 @@ -// Copyright (c) 2008, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "config.h" - -#if ENABLE(WORKERS) - -#include "v8_binding.h" -#include "v8_custom.h" -#include "v8_proxy.h" - -#include "ExceptionCode.h" -#include "Frame.h" -#include "MessagePort.h" -#include "V8Document.h" -#include "V8HTMLDocument.h" -#include "V8ObjectEventListener.h" -#include "Worker.h" -#include "WorkerContextExecutionProxy.h" - -namespace WebCore { - -CALLBACK_FUNC_DECL(WorkerConstructor) { - INC_STATS(L"DOM.Worker.Constructor"); - - if (!WorkerContextExecutionProxy::isWebWorkersEnabled()) { - V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "Worker is not enabled."); - return v8::Undefined(); - } - - if (!args.IsConstructCall()) { - V8Proxy::ThrowError(V8Proxy::TYPE_ERROR, - "DOM object constructor cannot be called as a function."); - return v8::Undefined(); - } - - if (args.Length() == 0) { - V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "Not enough arguments"); - return v8::Undefined(); - } - - v8::TryCatch try_catch; - v8::Handle<v8::String> script_url = args[0]->ToString(); - if (try_catch.HasCaught()) { - v8::ThrowException(try_catch.Exception()); - return v8::Undefined(); - } - if (script_url.IsEmpty()) { - return v8::Undefined(); - } - - // Get the document. - Frame* frame = V8Proxy::retrieveFrame(); - if (!frame) - return v8::Undefined(); - Document* document = frame->document(); - - // Create the worker object. - // Note: it's OK to let this RefPtr go out of scope because we also call - // SetDOMWrapper(), which effectively holds a reference to obj. - ExceptionCode ec = 0; - RefPtr<Worker> obj = Worker::create( - ToWebCoreString(script_url), document, ec); - - // Setup the standard wrapper object internal fields. - v8::Handle<v8::Object> wrapper_object = args.Holder(); - V8Proxy::SetDOMWrapper( - wrapper_object, V8ClassIndex::WORKER, obj.get()); - - obj->ref(); - V8Proxy::SetJSWrapperForActiveDOMObject( - obj.get(), v8::Persistent<v8::Object>::New(wrapper_object)); - - return wrapper_object; -} - -// TODO(mbelshe) - merge these with XHR's CreateHiddenXHRDependency - -// Use an array to hold dependents. It works like a ref-counted scheme. -// A value can be added more than once to the xhr object. -static void CreateHiddenDependency(v8::Local<v8::Object> object, - v8::Local<v8::Value> value) { - ASSERT(V8Proxy::GetDOMWrapperType(object) == - V8ClassIndex::WORKER); - v8::Local<v8::Value> cache = - object->GetInternalField(V8Custom::kWorkerRequestCacheIndex); - if (cache->IsNull() || cache->IsUndefined()) { - cache = v8::Array::New(); - object->SetInternalField(V8Custom::kWorkerRequestCacheIndex, cache); - } - - v8::Local<v8::Array> cache_array = v8::Local<v8::Array>::Cast(cache); - cache_array->Set(v8::Integer::New(cache_array->Length()), value); -} - -static void RemoveHiddenDependency(v8::Local<v8::Object> object, - v8::Local<v8::Value> value) { - ASSERT(V8Proxy::GetDOMWrapperType(object) == V8ClassIndex::WORKER); - v8::Local<v8::Value> cache = - object->GetInternalField(V8Custom::kWorkerRequestCacheIndex); - ASSERT(cache->IsArray()); - v8::Local<v8::Array> cache_array = v8::Local<v8::Array>::Cast(cache); - for (int i = cache_array->Length() - 1; i >= 0; i--) { - v8::Local<v8::Value> cached = cache_array->Get(v8::Integer::New(i)); - if (cached->StrictEquals(value)) { - cache_array->Delete(i); - return; - } - } - - // We should only get here if we try to remove an event listener that was - // never added. -} - -ACCESSOR_GETTER(WorkerOnmessage) { - INC_STATS(L"DOM.Worker.onmessage._get"); - Worker* imp = V8Proxy::ToNativeObject<Worker>( - V8ClassIndex::WORKER, info.Holder()); - if (imp->onmessage()) { - V8ObjectEventListener* listener = - static_cast<V8ObjectEventListener*>(imp->onmessage()); - v8::Local<v8::Object> v8_listener = listener->getListenerObject(); - return v8_listener; - } - return v8::Undefined(); -} - -ACCESSOR_SETTER(WorkerOnmessage) { - INC_STATS(L"DOM.Worker.onmessage._set"); - Worker* imp = V8Proxy::ToNativeObject<Worker>( - V8ClassIndex::WORKER, info.Holder()); - V8ObjectEventListener* old_listener = - static_cast<V8ObjectEventListener*>(imp->onmessage()); - if (value->IsNull()) { - if (old_listener) { - v8::Local<v8::Object> old_v8_listener = old_listener->getListenerObject(); - RemoveHiddenDependency(info.Holder(), old_v8_listener); - } - - // Clear the listener - imp->setOnmessage(0); - - } else { - V8Proxy* proxy = V8Proxy::retrieve(imp->scriptExecutionContext()); - if (!proxy) - return; - - RefPtr<EventListener> listener = - proxy->FindOrCreateObjectEventListener(value, false); - if (listener) { - if (old_listener) { - v8::Local<v8::Object> old_v8_listener = - old_listener->getListenerObject(); - RemoveHiddenDependency(info.Holder(), old_v8_listener); - } - - imp->setOnmessage(listener); - CreateHiddenDependency(info.Holder(), value); - } - } -} - -ACCESSOR_GETTER(WorkerOnerror) { - INC_STATS(L"DOM.Worker.onerror._get"); - Worker* imp = V8Proxy::ToNativeObject<Worker>( - V8ClassIndex::WORKER, info.Holder()); - if (imp->onerror()) { - V8ObjectEventListener* listener = - static_cast<V8ObjectEventListener*>(imp->onerror()); - v8::Local<v8::Object> v8_listener = listener->getListenerObject(); - return v8_listener; - } - return v8::Undefined(); -} - -ACCESSOR_SETTER(WorkerOnerror) { - INC_STATS(L"DOM.Worker.onerror._set"); - Worker* imp = V8Proxy::ToNativeObject<Worker>( - V8ClassIndex::WORKER, info.Holder()); - V8ObjectEventListener* old_listener = - static_cast<V8ObjectEventListener*>(imp->onerror()); - if (value->IsNull()) { - if (old_listener) { - v8::Local<v8::Object> old_v8_listener = - old_listener->getListenerObject(); - RemoveHiddenDependency(info.Holder(), old_v8_listener); - } - - // Clear the listener - imp->setOnerror(0); - } else { - V8Proxy* proxy = V8Proxy::retrieve(imp->scriptExecutionContext()); - if (!proxy) - return; - - RefPtr<EventListener> listener = - proxy->FindOrCreateObjectEventListener(value, false); - if (listener) { - if (old_listener) { - v8::Local<v8::Object> old_v8_listener = old_listener->getListenerObject(); - RemoveHiddenDependency(info.Holder(), old_v8_listener); - } - - imp->setOnerror(listener); - CreateHiddenDependency(info.Holder(), value); - } - } -} - -CALLBACK_FUNC_DECL(WorkerAddEventListener) { - INC_STATS(L"DOM.Worker.addEventListener()"); - Worker* imp = V8Proxy::ToNativeObject<Worker>( - V8ClassIndex::WORKER, args.Holder()); - - V8Proxy* proxy = V8Proxy::retrieve(imp->scriptExecutionContext()); - if (!proxy) - return v8::Undefined(); - - RefPtr<EventListener> listener = - proxy->FindOrCreateObjectEventListener(args[1], false); - if (listener) { - String type = ToWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - imp->addEventListener(type, listener, useCapture); - - CreateHiddenDependency(args.Holder(), args[1]); - } - return v8::Undefined(); -} - -CALLBACK_FUNC_DECL(WorkerRemoveEventListener) { - INC_STATS(L"DOM.Worker.removeEventListener()"); - Worker* imp = V8Proxy::ToNativeObject<Worker>( - V8ClassIndex::WORKER, args.Holder()); - - V8Proxy* proxy = V8Proxy::retrieve(imp->scriptExecutionContext()); - if (!proxy) - return v8::Undefined(); // probably leaked - - RefPtr<EventListener> listener = - proxy->FindObjectEventListener(args[1], false); - - if (listener) { - String type = ToWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - imp->removeEventListener(type, listener.get(), useCapture); - - RemoveHiddenDependency(args.Holder(), args[1]); - } - - return v8::Undefined(); -} - -} // namespace WebCore - -#endif // ENABLE(WORKERS) diff --git a/V8Binding/binding/dom_wrapper_map.h b/V8Binding/binding/dom_wrapper_map.h deleted file mode 100644 index e95ff88..0000000 --- a/V8Binding/binding/dom_wrapper_map.h +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BINDINGS_V8_DOM_WRAPPER_MAP -#define BINDINGS_V8_DOM_WRAPPER_MAP - -#include <v8.h> -#include <wtf/HashMap.h> - -// 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 { - public: - WeakReferenceMap(v8::WeakReferenceCallback callback) : - weak_reference_callback_(callback) { } -#ifndef NDEBUG - virtual ~WeakReferenceMap() { - if (map_.size() > 0) { - fprintf(stderr, "Leak %d JS wrappers.\n", map_.size()); - // Print out details. - } - } -#endif - - // Get the JS wrapper object of an object. - virtual v8::Persistent<ValueType> get(KeyType* obj) { - ValueType* wrapper = map_.get(obj); - return wrapper ? v8::Persistent<ValueType>(wrapper) - : v8::Persistent<ValueType>(); - } - - virtual void set(KeyType* obj, v8::Persistent<ValueType> wrapper) { - ASSERT(!map_.contains(obj)); - wrapper.MakeWeak(obj, weak_reference_callback_); - map_.set(obj, *wrapper); - } - - virtual void forget(KeyType* obj) { - ASSERT(obj); - ValueType* wrapper = map_.take(obj); - if (wrapper) { - v8::Persistent<ValueType> handle(wrapper); - handle.Dispose(); - handle.Clear(); - } - } - - bool contains(KeyType* obj) { - return map_.contains(obj); - } - - HashMap<KeyType*, ValueType*>& impl() { - return map_; - } - - protected: - HashMap<KeyType*, ValueType*> map_; - v8::WeakReferenceCallback weak_reference_callback_; -}; - - -template <class KeyType> -class DOMWrapperMap : public WeakReferenceMap<KeyType, v8::Object> { - public: - DOMWrapperMap(v8::WeakReferenceCallback callback) : - WeakReferenceMap<KeyType, v8::Object>(callback) { } -}; - -#endif // BINDINGS_V8_DOM_WRAPPER_MAP diff --git a/V8Binding/binding/npruntime.cpp b/V8Binding/binding/npruntime.cpp index f32c63d..6a2faeb 100644 --- a/V8Binding/binding/npruntime.cpp +++ b/V8Binding/binding/npruntime.cpp @@ -411,7 +411,7 @@ void _NPN_UnregisterObject(NPObject* obj) { g_live_objects.remove(sub_object); // Remove the JS references to the object. - ForgetV8ObjectForNPObject(sub_object); + forgetV8ObjectForNPObject(sub_object); ASSERT(set->size() < size); } @@ -425,8 +425,9 @@ void _NPN_UnregisterObject(NPObject* obj) { list->remove(obj); } } + g_live_objects.remove(obj); - ForgetV8ObjectForNPObject(obj); + forgetV8ObjectForNPObject(obj); } bool _NPN_IsAlive(NPObject* obj) { diff --git a/V8Binding/binding/v8_binding.cpp b/V8Binding/binding/v8_binding.cpp index 3a36fc5..616d7b2 100644 --- a/V8Binding/binding/v8_binding.cpp +++ b/V8Binding/binding/v8_binding.cpp @@ -37,10 +37,12 @@ class WebCoreStringResource: public v8::String::ExternalStringResource { String impl_; }; -String v8StringToWebCoreString(v8::Handle<v8::String> v8_str) { - if (v8_str->IsExternal()) { - WebCoreStringResource* str_resource = static_cast<WebCoreStringResource*>( - v8_str->GetExternalStringResource()); + +String v8StringToWebCoreString( + v8::Handle<v8::String> v8_str, bool externalize) { + WebCoreStringResource* str_resource = static_cast<WebCoreStringResource*>( + v8_str->GetExternalStringResource()); + if (str_resource) { return str_resource->webcore_string(); } @@ -48,53 +50,61 @@ String v8StringToWebCoreString(v8::Handle<v8::String> v8_str) { if (length == 0) { // Avoid trying to morph empty strings, as they do not have enough room to // contain the external reference. - return ""; + return StringImpl::empty(); } - // Copy the characters from the v8::String into a WebCore::String and allocate - // an external resource which will be attached to the v8::String. - String result; - const int kStringSizeToCopy = 256; - if (length < kStringSizeToCopy) { - uint16_t buffer[kStringSizeToCopy]; - v8_str->Write(buffer, 0, length); - result = StringImpl::create(reinterpret_cast<UChar*>(buffer), length); - } else { - StringBuffer buf(length); - v8_str->Write(reinterpret_cast<uint16_t*>(buf.characters()), 0, length); - result = String::adopt(buf); - } + UChar* buffer; + String result = String::createUninitialized(length, buffer); + v8_str->Write(reinterpret_cast<uint16_t*>(buffer), 0, length); -// -// TODO(mbelshe): Disable string morphing because it causes mystery -// perf regressions on intl1 and intl2 page cyclers. It works fine -// on machines other than the buildbots. -// -// WebCoreStringResource* resource = new WebCoreStringResource(result); -// if (!v8_str->MakeExternal(resource)) { -// // In case of a failure delete the external resource as it was not used. -// delete resource; -// } + if (externalize) { + WebCoreStringResource* resource = new WebCoreStringResource(result); + if (!v8_str->MakeExternal(resource)) { + // In case of a failure delete the external resource as it was not used. + delete resource; + } + } return result; } String v8ValueToWebCoreString(v8::Handle<v8::Value> obj) { - v8::Handle<v8::String> v8_str; if (obj->IsString()) { - v8_str = v8::Handle<v8::String>::Cast(obj); + v8::Handle<v8::String> v8_str = v8::Handle<v8::String>::Cast(obj); + String webCoreString = v8StringToWebCoreString(v8_str, true); + return webCoreString; + } else if (obj->IsInt32()) { + int value = obj->Int32Value(); + // Most numbers used are <= 100. Even if they aren't used + // there's very little in using the space. + const int kLowNumbers = 100; + static AtomicString lowNumbers[kLowNumbers + 1]; + String webCoreString; + if (0 <= value && value <= kLowNumbers) { + webCoreString = lowNumbers[value]; + if (!webCoreString) { + AtomicString valueString = AtomicString(String::number(value)); + lowNumbers[value] = valueString; + webCoreString = valueString; + } + } else { + webCoreString = String::number(value); + } + return webCoreString; } else { v8::TryCatch block; - v8_str = obj->ToString(); + v8::Handle<v8::String> v8_str = obj->ToString(); + // Check for empty handles to handle the case where an exception + // is thrown as part of invoking toString on the object. if (v8_str.IsEmpty()) - return ""; + return StringImpl::empty(); + return v8StringToWebCoreString(v8_str, false); } - return v8StringToWebCoreString(v8_str); } AtomicString v8StringToAtomicWebCoreString(v8::Handle<v8::String> v8_str) { - String str = v8StringToWebCoreString(v8_str); + String str = v8StringToWebCoreString(v8_str, true); return AtomicString(str); } @@ -108,13 +118,13 @@ AtomicString v8ValueToAtomicWebCoreString(v8::Handle<v8::Value> v8_str) { v8::Handle<v8::String> v8String(const String& str) { if (!str.length()) return v8::String::Empty(); - return v8::String::NewExternal(new WebCoreStringResource(str)); + return v8::String::NewExternal(new WebCoreStringResource(str)); } v8::Local<v8::String> v8ExternalString(const String& str) { if (!str.length()) return v8::String::Empty(); - return v8::String::NewExternal(new WebCoreStringResource(str)); + return v8::String::NewExternal(new WebCoreStringResource(str)); } } // namespace WebCore diff --git a/V8Binding/binding/v8_binding.h b/V8Binding/binding/v8_binding.h index 8300dd7..2882026 100644 --- a/V8Binding/binding/v8_binding.h +++ b/V8Binding/binding/v8_binding.h @@ -23,13 +23,18 @@ inline const uint16_t* FromWebCoreString(const String& str) { // Convert v8 types to a WebCore::String. If the V8 string is not already // an external string then it is transformed into an external string at this // point to avoid repeated conversions. -String v8StringToWebCoreString(v8::Handle<v8::String> obj); +String v8StringToWebCoreString( + v8::Handle<v8::String> obj, bool externalize); String v8ValueToWebCoreString(v8::Handle<v8::Value> obj); // TODO(mbelshe): drop this in favor of the type specific // v8ValueToWebCoreString when we rework the code generation. inline String ToWebCoreString(v8::Handle<v8::Value> obj) { - return v8ValueToWebCoreString(obj); + return v8ValueToWebCoreString(obj); +} + +inline String ToWebCoreString(v8::Handle<v8::String> string) { + return v8StringToWebCoreString(string, true); } // Convert v8 types to a WebCore::AtomicString. diff --git a/V8Binding/binding/v8_custom.cpp b/V8Binding/binding/v8_custom.cpp index 855e192..2af9cbd 100644 --- a/V8Binding/binding/v8_custom.cpp +++ b/V8Binding/binding/v8_custom.cpp @@ -1,10 +1,10 @@ /* * Copyright (C) 2000 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2004-2006 Apple Computer, Inc. + * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. * Copyright (C) 2006 James G. Speth (speth@end.com) * Copyright (C) 2006 Samuel Weinig (sam@webkit.org) - * Copyright 2007, 2008 Google Inc. All Rights Reserved. + * Copyright (C) 2007, 2008 Google Inc. All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -29,9 +29,7 @@ #include "v8_proxy.h" #include "v8_binding.h" #include "V8NPObject.h" -#include "v8_custom.h" -#include "V8Attr.h" #include "V8CanvasGradient.h" #include "V8CanvasPattern.h" #include "V8CustomEventListener.h" @@ -40,14 +38,15 @@ #include "V8HTMLCanvasElement.h" #include "V8HTMLDocument.h" #include "V8HTMLImageElement.h" -#include "V8HTMLOptionElement.h" +#include "V8NamedNodesCollection.h" #include "V8Node.h" - +#include "V8Proxy.h" #if ENABLE(XPATH) #include "V8XPathNSResolver.h" #include "V8XPathResult.h" #endif +#include "Attr.h" #include "Base64.h" #include "CanvasGradient.h" #include "CanvasPattern.h" @@ -59,13 +58,10 @@ #include "DOMParser.h" #include "DOMStringList.h" #include "DOMTimer.h" -#include "DOMWindow.h" #include "Document.h" #include "DocumentFragment.h" #include "Event.h" -#include "EventListener.h" #include "EventTarget.h" -#include "ExceptionCode.h" #include "FloatRect.h" #include "Frame.h" #include "FrameLoader.h" @@ -74,20 +70,11 @@ #include "HTMLCanvasElement.h" #include "HTMLDocument.h" #include "HTMLEmbedElement.h" -#include "HTMLFormElement.h" -#include "HTMLFrameElement.h" -#include "HTMLFrameElementBase.h" -#include "HTMLFrameSetElement.h" -#include "HTMLIFrameElement.h" #include "HTMLImageElement.h" #include "HTMLInputElement.h" #include "HTMLNames.h" -#include "HTMLOptionElement.h" -#include "HTMLOptionsCollection.h" -#include "HTMLSelectElement.h" #include "History.h" #include "JSXPathNSResolver.h" -#include "JSDOMBinding.h" #include "KURL.h" #include "Location.h" #include "MessageChannel.h" @@ -156,849 +143,7 @@ ACCESSOR_GETTER(DocumentImplementation) { return wrapper; } - -ACCESSOR_GETTER(DocumentLocation) { - Document* imp = V8Proxy::DOMWrapperToNative<Document>(info.Holder()); - if (!imp->frame()) - return v8::Null(); - - DOMWindow* window = imp->frame()->domWindow(); - return V8Proxy::ToV8Object(V8ClassIndex::LOCATION, window->location()); -} - - -ACCESSOR_SETTER(DocumentLocation) { - Document* imp = V8Proxy::DOMWrapperToNative<Document>(info.Holder()); - if (!imp->frame()) - return; - - DOMWindow* window = imp->frame()->domWindow(); - // WindowSetLocation does security checks. // XXXMB- verify! - WindowSetLocation(window, ToWebCoreString(value)); -} - - -INDEXED_PROPERTY_GETTER(HTMLFormElement) { - INC_STATS("DOM.HTMLFormElement.IndexedPropertyGetter"); - HTMLFormElement* form = - V8Proxy::DOMWrapperToNode<HTMLFormElement>(info.Holder()); - - RefPtr<Node> result = form->elements()->item(index); - if (!result) return v8::Handle<v8::Value>(); - return V8Proxy::NodeToV8Object(result.get()); -} - - -INDEXED_PROPERTY_GETTER(HTMLOptionsCollection) { - INC_STATS("DOM.HTMLOptionsCollection.IndexedPropertyGetter"); - HTMLOptionsCollection* collection = - V8Proxy::ToNativeObject<HTMLOptionsCollection>( - V8ClassIndex::HTMLOPTIONSCOLLECTION, info.Holder()); - - RefPtr<Node> result = collection->item(index); - if (!result) return v8::Handle<v8::Value>(); - - return V8Proxy::NodeToV8Object(result.get()); -} - -static v8::Handle<v8::Value> OptionsCollectionSetter(uint32_t index, - v8::Handle<v8::Value> value, HTMLSelectElement* base) { - if (value->IsNull() || value->IsUndefined()) { - base->remove(index); - return value; - } - - ExceptionCode ec = 0; - - // Check that the value is an HTMLOptionElement. If not, throw a - // TYPE_MISMATCH_ERR DOMException. - if (!V8HTMLOptionElement::HasInstance(value)) { - V8Proxy::SetDOMException(TYPE_MISMATCH_ERR); - return value; - } - - HTMLOptionElement* element = - V8Proxy::DOMWrapperToNode<HTMLOptionElement>( - v8::Handle<v8::Object>::Cast(value)); - base->setOption(index, element, ec); - - V8Proxy::SetDOMException(ec); - return value; -} - - -INDEXED_PROPERTY_SETTER(HTMLOptionsCollection) { - INC_STATS("DOM.HTMLOptionsCollection.IndexedPropertySetter"); - HTMLOptionsCollection* collection = - V8Proxy::ToNativeObject<HTMLOptionsCollection>( - V8ClassIndex::HTMLOPTIONSCOLLECTION, info.Holder()); - HTMLSelectElement* base = static_cast<HTMLSelectElement*>(collection->base()); - return OptionsCollectionSetter(index, value, base); -} - - -INDEXED_PROPERTY_SETTER(HTMLSelectElementCollection) { - INC_STATS("DOM.HTMLSelectElementCollection.IndexedPropertySetter"); - HTMLSelectElement* select = - V8Proxy::DOMWrapperToNode<HTMLSelectElement>(info.Holder()); - return OptionsCollectionSetter(index, value, select); -} - -// CanvasRenderingContext2D ---------------------------------------------------- - -// Helper macro for converting v8 values into floats (expected by many of the -// canvas functions). -#define TO_FLOAT(a) static_cast<float>((a)->NumberValue()) - -// TODO: SetStrokeColor and SetFillColor are similar except function names, -// consolidate them into one. -CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetStrokeColor) { - INC_STATS("DOM.CanvasRenderingContext2D.setStrokeColor()"); - CanvasRenderingContext2D* context = - V8Proxy::ToNativeObject<CanvasRenderingContext2D>( - V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); - switch (args.Length()) { - case 1: - if (args[0]->IsString()) { - context->setStrokeColor(ToWebCoreString(args[0])); - } else { - context->setStrokeColor(TO_FLOAT(args[0])); - } - break; - case 2: - if (args[0]->IsString()) { - context->setStrokeColor(ToWebCoreString(args[0]), - TO_FLOAT(args[1])); - } else { - context->setStrokeColor(TO_FLOAT(args[0]), - TO_FLOAT(args[1])); - } - break; - case 4: - context->setStrokeColor(TO_FLOAT(args[0]), - TO_FLOAT(args[1]), - TO_FLOAT(args[2]), - TO_FLOAT(args[3])); - break; - case 5: - context->setStrokeColor(TO_FLOAT(args[0]), - TO_FLOAT(args[1]), - TO_FLOAT(args[2]), - TO_FLOAT(args[3]), - TO_FLOAT(args[4])); - break; - default: - V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, - "setStrokeColor: Invalid number of arguments"); - break; - } - return v8::Undefined(); -} - -CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetFillColor) { - INC_STATS("DOM.CanvasRenderingContext2D.setFillColor()"); - CanvasRenderingContext2D* context = - V8Proxy::ToNativeObject<CanvasRenderingContext2D>( - V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); - switch (args.Length()) { - case 1: - if (args[0]->IsString()) { - context->setFillColor(ToWebCoreString(args[0])); - } else { - context->setFillColor(TO_FLOAT(args[0])); - } - break; - case 2: - if (args[0]->IsString()) { - context->setFillColor(ToWebCoreString(args[0]), TO_FLOAT(args[1])); - } else { - context->setFillColor(TO_FLOAT(args[0]), TO_FLOAT(args[1])); - } - break; - case 4: - context->setFillColor(TO_FLOAT(args[0]), - TO_FLOAT(args[1]), - TO_FLOAT(args[2]), - TO_FLOAT(args[3])); - break; - case 5: - context->setFillColor(TO_FLOAT(args[0]), - TO_FLOAT(args[1]), - TO_FLOAT(args[2]), - TO_FLOAT(args[3]), - TO_FLOAT(args[4])); - break; - default: - V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, - "setFillColor: Invalid number of arguments"); - break; - } - return v8::Undefined(); -} - -CALLBACK_FUNC_DECL(CanvasRenderingContext2DStrokeRect) { - INC_STATS("DOM.CanvasRenderingContext2D.strokeRect()"); - CanvasRenderingContext2D* context = - V8Proxy::ToNativeObject<CanvasRenderingContext2D>( - V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); - if (args.Length() == 5) { - context->strokeRect(TO_FLOAT(args[0]), - TO_FLOAT(args[1]), - TO_FLOAT(args[2]), - TO_FLOAT(args[3]), - TO_FLOAT(args[4])); - } else if (args.Length() == 4) { - context->strokeRect(TO_FLOAT(args[0]), - TO_FLOAT(args[1]), - TO_FLOAT(args[2]), - TO_FLOAT(args[3])); - } else { - V8Proxy::SetDOMException(INDEX_SIZE_ERR); - return v8::Handle<v8::Value>(); - } - - return v8::Undefined(); -} - -CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetShadow) { - INC_STATS("DOM.CanvasRenderingContext2D.setShadow()"); - CanvasRenderingContext2D* context = - V8Proxy::ToNativeObject<CanvasRenderingContext2D>( - V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); - - switch (args.Length()) { - case 3: - context->setShadow(TO_FLOAT(args[0]), TO_FLOAT(args[1]), - TO_FLOAT(args[2])); - break; - case 4: - if (args[3]->IsString()) - context->setShadow(TO_FLOAT(args[0]), TO_FLOAT(args[1]), - TO_FLOAT(args[2]), ToWebCoreString(args[3])); - else - context->setShadow(TO_FLOAT(args[0]), TO_FLOAT(args[1]), - TO_FLOAT(args[2]), TO_FLOAT(args[3])); - break; - case 5: - if (args[3]->IsString()) - context->setShadow(TO_FLOAT(args[0]), TO_FLOAT(args[1]), - TO_FLOAT(args[2]), ToWebCoreString(args[3]), - TO_FLOAT(args[4])); - else - context->setShadow(TO_FLOAT(args[0]), TO_FLOAT(args[1]), - TO_FLOAT(args[2]), TO_FLOAT(args[3]), - TO_FLOAT(args[4])); - break; - case 7: - context->setShadow(TO_FLOAT(args[0]), TO_FLOAT(args[1]), - TO_FLOAT(args[2]), TO_FLOAT(args[3]), - TO_FLOAT(args[4]), TO_FLOAT(args[5]), - TO_FLOAT(args[6])); - break; - case 8: - context->setShadow(TO_FLOAT(args[0]), TO_FLOAT(args[1]), - TO_FLOAT(args[2]), TO_FLOAT(args[3]), - TO_FLOAT(args[4]), TO_FLOAT(args[5]), - TO_FLOAT(args[6]), TO_FLOAT(args[7])); - break; - default: - V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, - "setShadow: Invalid number of arguments"); - break; - } - - return v8::Undefined(); -} - -CALLBACK_FUNC_DECL(CanvasRenderingContext2DDrawImage) { - INC_STATS("DOM.CanvasRenderingContext2D.drawImage()"); - CanvasRenderingContext2D* context = - V8Proxy::ToNativeObject<CanvasRenderingContext2D>( - V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); - - v8::Handle<v8::Value> arg = args[0]; - - if (V8HTMLImageElement::HasInstance(arg)) { - ExceptionCode ec = 0; - HTMLImageElement* image_element = - V8Proxy::DOMWrapperToNode<HTMLImageElement>(arg); - switch (args.Length()) { - case 3: - context->drawImage(image_element, TO_FLOAT(args[1]), TO_FLOAT(args[2])); - break; - case 5: - context->drawImage(image_element, TO_FLOAT(args[1]), TO_FLOAT(args[2]), - TO_FLOAT(args[3]), TO_FLOAT(args[4]), ec); - if (ec != 0) { - V8Proxy::SetDOMException(ec); - return v8::Handle<v8::Value>(); - } - break; - case 9: - context->drawImage(image_element, - FloatRect(TO_FLOAT(args[1]), TO_FLOAT(args[2]), - TO_FLOAT(args[3]), TO_FLOAT(args[4])), - FloatRect(TO_FLOAT(args[5]), TO_FLOAT(args[6]), - TO_FLOAT(args[7]), TO_FLOAT(args[8])), - ec); - if (ec != 0) { - V8Proxy::SetDOMException(ec); - return v8::Handle<v8::Value>(); - } - break; - default: - V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, - "drawImage: Invalid number of arguments"); - return v8::Undefined(); - } - return v8::Undefined(); - } - - // HTMLCanvasElement - if (V8HTMLCanvasElement::HasInstance(arg)) { - ExceptionCode ec = 0; - HTMLCanvasElement* canvas_element = - V8Proxy::DOMWrapperToNode<HTMLCanvasElement>(arg); - switch (args.Length()) { - case 3: - context->drawImage(canvas_element, TO_FLOAT(args[1]), TO_FLOAT(args[2])); - break; - case 5: - context->drawImage(canvas_element, TO_FLOAT(args[1]), TO_FLOAT(args[2]), - TO_FLOAT(args[3]), TO_FLOAT(args[4]), ec); - if (ec != 0) { - V8Proxy::SetDOMException(ec); - return v8::Handle<v8::Value>(); - } - break; - case 9: - context->drawImage(canvas_element, - FloatRect(TO_FLOAT(args[1]), TO_FLOAT(args[2]), - TO_FLOAT(args[3]), TO_FLOAT(args[4])), - FloatRect(TO_FLOAT(args[5]), TO_FLOAT(args[6]), - TO_FLOAT(args[7]), TO_FLOAT(args[8])), - ec); - if (ec != 0) { - V8Proxy::SetDOMException(ec); - return v8::Handle<v8::Value>(); - } - break; - default: - V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, - "drawImage: Invalid number of arguments"); - return v8::Undefined(); - } - return v8::Undefined(); - } - - V8Proxy::SetDOMException(TYPE_MISMATCH_ERR); - return v8::Handle<v8::Value>(); -} - -CALLBACK_FUNC_DECL(CanvasRenderingContext2DDrawImageFromRect) { - INC_STATS("DOM.CanvasRenderingContext2D.drawImageFromRect()"); - CanvasRenderingContext2D* context = - V8Proxy::ToNativeObject<CanvasRenderingContext2D>( - V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); - - v8::Handle<v8::Value> arg = args[0]; - - if (V8HTMLImageElement::HasInstance(arg)) { - HTMLImageElement* image_element = - V8Proxy::DOMWrapperToNode<HTMLImageElement>(arg); - context->drawImageFromRect(image_element, - TO_FLOAT(args[1]), TO_FLOAT(args[2]), - TO_FLOAT(args[3]), TO_FLOAT(args[4]), - TO_FLOAT(args[5]), TO_FLOAT(args[6]), - TO_FLOAT(args[7]), TO_FLOAT(args[8]), - ToWebCoreString(args[9])); - } else { - V8Proxy::ThrowError(V8Proxy::TYPE_ERROR, - "drawImageFromRect: Invalid type of arguments"); - } - - return v8::Undefined(); -} - -CALLBACK_FUNC_DECL(CanvasRenderingContext2DCreatePattern) { - INC_STATS("DOM.CanvasRenderingContext2D.createPattern()"); - CanvasRenderingContext2D* context = - V8Proxy::ToNativeObject<CanvasRenderingContext2D>( - V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); - - v8::Handle<v8::Value> arg = args[0]; - - if (V8HTMLImageElement::HasInstance(arg)) { - HTMLImageElement* image_element = - V8Proxy::DOMWrapperToNode<HTMLImageElement>(arg); - ExceptionCode ec = 0; - RefPtr<CanvasPattern> pattern = - context->createPattern(image_element, valueToStringWithNullCheck(args[1]), ec); - if (ec != 0) { - V8Proxy::SetDOMException(ec); - return v8::Handle<v8::Value>(); - } - return V8Proxy::ToV8Object(V8ClassIndex::CANVASPATTERN, pattern.get()); - } - - if (V8HTMLCanvasElement::HasInstance(arg)) { - HTMLCanvasElement* canvas_element = - V8Proxy::DOMWrapperToNode<HTMLCanvasElement>(arg); - ExceptionCode ec = 0; - RefPtr<CanvasPattern> pattern = - context->createPattern(canvas_element, valueToStringWithNullCheck(args[1]), ec); - if (ec != 0) { - V8Proxy::SetDOMException(ec); - return v8::Handle<v8::Value>(); - } - return V8Proxy::ToV8Object(V8ClassIndex::CANVASPATTERN, pattern.get()); - } - - V8Proxy::SetDOMException(TYPE_MISMATCH_ERR); - return v8::Handle<v8::Value>(); -} - -CALLBACK_FUNC_DECL(CanvasRenderingContext2DFillText) { - INC_STATS("DOM.CanvasRenderingContext2D.fillText()"); - - CanvasRenderingContext2D* context = - V8Proxy::ToNativeObject<CanvasRenderingContext2D>( - V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); - - // Two forms: - // * fillText(text, x, y) - // * fillText(text, x, y, maxWidth) - if (args.Length() < 3 || args.Length() > 4) { - V8Proxy::SetDOMException(SYNTAX_ERR); - return v8::Handle<v8::Value>(); - } - - String text = ToWebCoreString(args[0]); - float x = TO_FLOAT(args[1]); - float y = TO_FLOAT(args[2]); - - if (args.Length() == 4) { - float maxWidth = TO_FLOAT(args[3]); - context->fillText(text, x, y, maxWidth); - } else { - context->fillText(text, x, y); - } - - return v8::Undefined(); -} - -CALLBACK_FUNC_DECL(CanvasRenderingContext2DStrokeText) { - INC_STATS("DOM.CanvasRenderingContext2D.strokeText()"); - - CanvasRenderingContext2D* context = - V8Proxy::ToNativeObject<CanvasRenderingContext2D>( - V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); - - // Two forms: - // * strokeText(text, x, y) - // * strokeText(text, x, y, maxWidth) - if (args.Length() < 3 || args.Length() > 4) { - V8Proxy::SetDOMException(SYNTAX_ERR); - return v8::Handle<v8::Value>(); - } - - String text = ToWebCoreString(args[0]); - float x = TO_FLOAT(args[1]); - float y = TO_FLOAT(args[2]); - - if (args.Length() == 4) { - float maxWidth = TO_FLOAT(args[3]); - context->strokeText(text, x, y, maxWidth); - } else { - context->strokeText(text, x, y); - } - - return v8::Undefined(); -} - -CALLBACK_FUNC_DECL(CanvasRenderingContext2DPutImageData) { - INC_STATS("DOM.CanvasRenderingContext2D.putImageData()"); - - // Two froms: - // * putImageData(ImageData, x, y) - // * putImageData(ImageData, x, y, dirtyX, dirtyY, dirtyWidth, dirtyHeight) - if (args.Length() != 3 && args.Length() != 7) { - V8Proxy::SetDOMException(SYNTAX_ERR); - return v8::Handle<v8::Value>(); - } - - CanvasRenderingContext2D* context = - V8Proxy::ToNativeObject<CanvasRenderingContext2D>( - V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); - - ImageData* imageData = 0; - - // Need to check that the argument is of the correct type, since - // ToNativeObject() 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 (V8Proxy::IsWrapperOfType(args[0], V8ClassIndex::IMAGEDATA)) { - imageData = V8Proxy::ToNativeObject<ImageData>( - V8ClassIndex::IMAGEDATA, args[0]); - } - - ExceptionCode ec = 0; - - if (args.Length() == 7) { - context->putImageData(imageData, - TO_FLOAT(args[1]), TO_FLOAT(args[2]), TO_FLOAT(args[3]), - TO_FLOAT(args[4]), TO_FLOAT(args[5]), TO_FLOAT(args[6]), ec); - } else { - context->putImageData(imageData, TO_FLOAT(args[1]), TO_FLOAT(args[2]), ec); - } - - if (ec != 0) { - V8Proxy::SetDOMException(ec); - return v8::Handle<v8::Value>(); - } - - return v8::Undefined(); -} - -static bool AllowSettingSrcToJavascriptURL(Element* element, String name, - String value) { - // Need to parse value as URL first in order to check its protocol. - // " javascript:", "java\0script:", "javascript\t:", "javascript\1:" - // are all parsed as "javascript:" url. - // When changing location in HTMLFrameElement, value is parsed as url. - // We must match the behavior there. - // See issue 804099. - // - // parseURL is defined in CSSHelper.cpp. - if ((element->hasTagName(HTMLNames::iframeTag) || - element->hasTagName(HTMLNames::frameTag)) && - equalIgnoringCase(name, "src") && - parseURL(value).startsWith("javascript:", false)) { - HTMLFrameElementBase* frame = static_cast<HTMLFrameElementBase*>(element); - Node* contentDoc = frame->contentDocument(); - if (contentDoc && !V8Proxy::CheckNodeSecurity(contentDoc)) - return false; - } - return true; -} - - -static bool AllowSettingFrameSrcToJavascriptUrl(HTMLFrameElementBase* frame, - String value) { - // See same issue in AllowSettingSrcToJavascriptURL. - if (parseURL(value).startsWith("javascript:", false)) { - Node* contentDoc = frame->contentDocument(); - if (contentDoc && !V8Proxy::CheckNodeSecurity(contentDoc)) - return false; - } - return true; -} - - -// HTMLIFrameElement ----------------------------------------------------------- - -// TODO(mbelshe): This should move into V8DOMWindowCustom.cpp -// Can't move it right now because it depends on V8ScheduledAction, -// which is private to this file (v8_custom.cpp). -v8::Handle<v8::Value> V8Custom::WindowSetTimeoutImpl(const v8::Arguments& args, - bool single_shot) { - int num_arguments = args.Length(); - - if (num_arguments < 1) return v8::Undefined(); - - DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>( - V8ClassIndex::DOMWINDOW, args.Holder()); - - if (!imp->frame()) - return v8::Undefined(); - - if (!V8Proxy::CanAccessFrame(imp->frame(), true)) - return v8::Undefined(); - - ScriptExecutionContext* script_context = - static_cast<ScriptExecutionContext*>(imp->frame()->document()); - - v8::Handle<v8::Value> function = args[0]; - - int32_t timeout = 0; - if (num_arguments >= 2) timeout = args[1]->Int32Value(); - - int id; - if (function->IsString()) { - // Don't allow setting timeouts to run empty functions! - // (Bug 1009597) - WebCore::String string_function = ToWebCoreString(function); - if (string_function.length() == 0) - return v8::Undefined(); - - id = DOMTimer::install(script_context, - new ScheduledAction(string_function), timeout, - single_shot); - } else if (function->IsFunction()) { - int param_count = num_arguments >= 2 ? num_arguments - 2 : 0; - v8::Local<v8::Value>* params = 0; - if (param_count > 0) { - params = new v8::Local<v8::Value>[param_count]; - for (int i = 0; i < param_count; i++) - // parameters must be globalized - params[i] = args[i+2]; - } - - // params is passed to action, and released in action's destructor - ScheduledAction* action = new ScheduledAction( - v8::Handle<v8::Function>::Cast(function), param_count, params); - - delete[] params; - - id = DOMTimer::install(script_context, action, timeout, single_shot); - } else { - // TODO(fqian): what's the right return value if failed. - return v8::Undefined(); - } - return v8::Integer::New(id); -} - - -// DOMWindow ------------------------------------------------------------------- - -static bool IsAscii(const String& str) { - for (size_t i = 0; i < str.length(); i++) { - if (str[i] > 0xFF) - return false; - } - return true; -} - -static v8::Handle<v8::Value> Base64Convert(const String& str, bool encode) { - if (!IsAscii(str)) { - V8Proxy::SetDOMException(INVALID_CHARACTER_ERR); - return v8::Handle<v8::Value>(); - } - - Vector<char> in(str.length()); - for (size_t i = 0; i < str.length(); i++) { - in[i] = static_cast<char>(str[i]); - } - Vector<char> out; - - if (encode) { - base64Encode(in, out); - } else { - if (!base64Decode(in, out)) { - V8Proxy::ThrowError(V8Proxy::GENERAL_ERROR, "Cannot decode base64"); - return v8::Undefined(); - } - } - - return v8String(String(out.data(), out.size())); -} - -CALLBACK_FUNC_DECL(DOMWindowAtob) { - INC_STATS("DOM.DOMWindow.atob()"); - DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>( - V8ClassIndex::DOMWINDOW, args.Holder()); - - if (!V8Proxy::CanAccessFrame(imp->frame(), true)) - return v8::Undefined(); - - if (args.Length() < 1) { - V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "Not enough arguments"); - return v8::Undefined(); - } - - if (args[0]->IsNull()) return v8String(""); - - String str = ToWebCoreString(args[0]); - return Base64Convert(str, false); -} - -CALLBACK_FUNC_DECL(DOMWindowBtoa) { - INC_STATS("DOM.DOMWindow.btoa()"); - DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>( - V8ClassIndex::DOMWINDOW, args.Holder()); - - if (!V8Proxy::CanAccessFrame(imp->frame(), true)) - return v8::Undefined(); - - if (args.Length() < 1) { - V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "Not enough arguments"); - return v8::Undefined(); - } - - if (args[0]->IsNull()) return v8String(""); - - String str = ToWebCoreString(args[0]); - return Base64Convert(str, true); -} - -// TODO(fqian): returning string is cheating, and we should -// fix this by calling toString function on the receiver. -// However, V8 implements toString in JavaScript, which requires -// switching context of receiver. I consider it is dangerous. -CALLBACK_FUNC_DECL(DOMWindowToString) -{ - INC_STATS("DOM.DOMWindow.toString()"); - return args.This()->ObjectProtoToString(); -} - -CALLBACK_FUNC_DECL(DOMWindowNOP) -{ - INC_STATS("DOM.DOMWindow.nop()"); - return v8::Undefined(); -} - - -CALLBACK_FUNC_DECL(HTMLFormElementSubmit) { - INC_STATS("DOM.HTMLFormElement.submit()"); - - HTMLFormElement* form = - V8Proxy::DOMWrapperToNative<HTMLFormElement>(args.Holder()); - - form->submit(0, false, false); - return v8::Undefined(); -} - -static String EventNameFromAttributeName(const String& name) { - ASSERT(name.startsWith("on")); - String event_type = name.substring(2); - - if (event_type.startsWith("w")) { - switch(event_type[event_type.length() - 1]) { - case 't': - event_type = "webkitAnimationStart"; - break; - case 'n': - event_type = "webkitAnimationIteration"; - break; - case 'd': - ASSERT(event_type.length() > 7); - if (event_type[7] == 'a') - event_type = "webkitAnimationEnd"; - else - event_type = "webkitTransitionEnd"; - break; - } - } - - return event_type; -} - - -ACCESSOR_SETTER(DOMWindowEventHandler) { - v8::Handle<v8::Object> holder = V8Proxy::LookupDOMWrapper( - V8ClassIndex::DOMWINDOW, info.This()); - if (holder.IsEmpty()) - return; - - DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>( - V8ClassIndex::DOMWINDOW, holder); - if (!imp->frame()) - return; - - Document* doc = imp->frame()->document(); - if (!doc) - return; - - String key = ToWebCoreString(name); - String event_type = EventNameFromAttributeName(key); - - if (value->IsNull()) { - // Clear the event listener - doc->removeWindowInlineEventListenerForType(event_type); - } else { - V8Proxy* proxy = V8Proxy::retrieve(imp->frame()); - if (!proxy) - return; - - RefPtr<EventListener> listener = - proxy->FindOrCreateV8EventListener(value, true); - if (listener) { - doc->setWindowInlineEventListenerForType(event_type, listener); - } - } -} - - -ACCESSOR_GETTER(DOMWindowEventHandler) { - v8::Handle<v8::Object> holder = V8Proxy::LookupDOMWrapper( - V8ClassIndex::DOMWINDOW, info.This()); - if (holder.IsEmpty()) - return v8::Undefined(); - - DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>( - V8ClassIndex::DOMWINDOW, holder); - if (!imp->frame()) - return v8::Undefined(); - - Document* doc = imp->frame()->document(); - if (!doc) - return v8::Undefined(); - - String key = ToWebCoreString(name); - String event_type = EventNameFromAttributeName(key); - - EventListener* listener = doc->windowInlineEventListenerForType(event_type); - return V8Proxy::EventListenerToV8Object(listener); -} - - // --------------- Security Checks ------------------------- -NAMED_ACCESS_CHECK(DOMWindow) { - ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::DOMWINDOW); - v8::Handle<v8::Value> window = - V8Proxy::LookupDOMWrapper(V8ClassIndex::DOMWINDOW, host); - if (window.IsEmpty()) - return false; // the frame is gone. - - DOMWindow* target_win = - V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, window); - - ASSERT(target_win); - - Frame* target = target_win->frame(); - if (!target) - return false; - - if (key->IsString()) { - String name = ToWebCoreString(key); - - // Allow access of GET and HAS if index is a subframe. - if ((type == v8::ACCESS_GET || type == v8::ACCESS_HAS) && - target->tree()->child(name)) { - return true; - } - } - - return V8Proxy::CanAccessFrame(target, false); -} - - -INDEXED_ACCESS_CHECK(DOMWindow) { - ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::DOMWINDOW); - v8::Handle<v8::Value> window = - V8Proxy::LookupDOMWrapper(V8ClassIndex::DOMWINDOW, host); - if (window.IsEmpty()) - return false; - - DOMWindow* target_win = - V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, window); - - ASSERT(target_win); - - Frame* target = target_win->frame(); - if (!target) - return false; - - // Allow access of GET and HAS if index is a subframe. - if ((type == v8::ACCESS_GET || type == v8::ACCESS_HAS) && - target->tree()->child(index)) { - return true; - } - - return V8Proxy::CanAccessFrame(target, false); -} - - INDEXED_ACCESS_CHECK(History) { ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::HISTORY); // Only allow same origin access diff --git a/V8Binding/binding/v8_custom.h b/V8Binding/binding/v8_custom.h index caeac41..3e8f52e 100644 --- a/V8Binding/binding/v8_custom.h +++ b/V8Binding/binding/v8_custom.h @@ -121,14 +121,34 @@ class V8Custom { kDefaultWrapperInternalFieldCount + 1; #endif - static const int kDOMWindowHistoryIndex = + static const int kDOMWindowConsoleIndex = kDefaultWrapperInternalFieldCount + 0; - static const int kDOMWindowNavigatorIndex = + static const int kDOMWindowHistoryIndex = kDefaultWrapperInternalFieldCount + 1; - static const int kDOMWindowLocationIndex = + static const int kDOMWindowLocationbarIndex = kDefaultWrapperInternalFieldCount + 2; - static const int kDOMWindowInternalFieldCount = + 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 kDOMWindowInternalFieldCount = + kDefaultWrapperInternalFieldCount + 13; static const int kStyleSheetOwnerNodeIndex = kDefaultWrapperInternalFieldCount + 0; @@ -220,6 +240,8 @@ static bool v8##NAME##IndexedSecurityCheck(v8::Local<v8::Object> host, \ DECLARE_PROPERTY_ACCESSOR(CanvasRenderingContext2DStrokeStyle) DECLARE_PROPERTY_ACCESSOR(CanvasRenderingContext2DFillStyle) +DECLARE_PROPERTY_ACCESSOR_GETTER(DOMWindowEvent) +DECLARE_PROPERTY_ACCESSOR_GETTER(DOMWindowCrypto) // Customized getter&setter of DOMWindow.location DECLARE_PROPERTY_ACCESSOR_SETTER(DOMWindowLocation) // Customized setter of DOMWindow.opener @@ -304,6 +326,8 @@ DECLARE_CALLBACK(DOMWindowClearTimeout) DECLARE_CALLBACK(DOMWindowClearInterval) DECLARE_CALLBACK(DOMParserConstructor) +DECLARE_CALLBACK(HTMLImageElementConstructor) +DECLARE_CALLBACK(HTMLOptionElementConstructor) DECLARE_CALLBACK(MessageChannelConstructor) DECLARE_CALLBACK(WebKitCSSMatrixConstructor) DECLARE_CALLBACK(WebKitPointConstructor) @@ -368,10 +392,13 @@ DECLARE_CALLBACK(LocationReload) DECLARE_CALLBACK(LocationToString) DECLARE_CALLBACK(LocationValueOf) -// Implementation of EventTarget::addEventListener -// and EventTarget::removeEventListener +// Implementation of custom Node methods. DECLARE_CALLBACK(NodeAddEventListener) DECLARE_CALLBACK(NodeRemoveEventListener) +DECLARE_CALLBACK(NodeInsertBefore) +DECLARE_CALLBACK(NodeReplaceChild) +DECLARE_CALLBACK(NodeRemoveChild) +DECLARE_CALLBACK(NodeAppendChild) // Custom implementation is Navigator properties. // We actually only need this because WebKit has @@ -416,6 +443,16 @@ DECLARE_CALLBACK(TreeWalkerNextSibling) DECLARE_CALLBACK(TreeWalkerPreviousSibling) // Custom implementation of InspectorController functions +DECLARE_CALLBACK(InspectorControllerProfiles) +DECLARE_CALLBACK(InspectorControllerHighlightDOMNode) +DECLARE_CALLBACK(InspectorControllerAddResourceSourceToFrame) +DECLARE_CALLBACK(InspectorControllerGetResourceDocumentNode) +DECLARE_CALLBACK(InspectorControllerAddSourceToFrame) +DECLARE_CALLBACK(InspectorControllerSearch) +DECLARE_CALLBACK(InspectorControllerSetting) +DECLARE_CALLBACK(InspectorControllerInspectedWindow) +DECLARE_CALLBACK(InspectorControllerSetSetting) +DECLARE_CALLBACK(InspectorControllerCurrentCallFrame) DECLARE_CALLBACK(InspectorControllerDebuggerEnabled) DECLARE_CALLBACK(InspectorControllerPauseOnExceptions) DECLARE_CALLBACK(InspectorControllerProfilerEnabled) @@ -461,6 +498,7 @@ DECLARE_INDEXED_PROPERTY_GETTER(NamedNodeMap) DECLARE_INDEXED_PROPERTY_GETTER(HTMLFormElement) DECLARE_INDEXED_PROPERTY_GETTER(HTMLOptionsCollection) DECLARE_INDEXED_PROPERTY_SETTER(HTMLOptionsCollection) +DECLARE_NAMED_PROPERTY_GETTER(HTMLSelectElementCollection) DECLARE_INDEXED_PROPERTY_SETTER(HTMLSelectElementCollection) DECLARE_NAMED_PROPERTY_GETTER(HTMLCollection) @@ -481,6 +519,9 @@ DECLARE_CALLBACK(DatabaseTransaction) DECLARE_CALLBACK(SQLTransactionExecuteSql) DECLARE_CALLBACK(SQLResultSetRowListItem) +// ClientRectList +DECLARE_INDEXED_PROPERTY_GETTER(ClientRectList) + // SVG custom properties and callbacks #if ENABLE(SVG) DECLARE_PROPERTY_ACCESSOR_GETTER(SVGLengthValue) diff --git a/V8Binding/binding/v8_proxy.cpp b/V8Binding/binding/v8_proxy.cpp index 45b56d7..d3c5db9 100644 --- a/V8Binding/binding/v8_proxy.cpp +++ b/V8Binding/binding/v8_proxy.cpp @@ -48,9 +48,10 @@ #if PLATFORM(CHROMIUM) #include "ChromiumBridge.h" #endif +#include "CSSMutableStyleDeclaration.h" #include "DOMObjectsInclude.h" - +#include "DocumentLoader.h" #include "ScriptController.h" #include "V8DOMMap.h" @@ -58,91 +59,6 @@ namespace WebCore { -V8EventListenerList::V8EventListenerList(const char* name) -{ - ASSERT(strlen(name) <= kMaxKeyNameLength); - v8::HandleScope handleScope; - - // Write the name into a temporary buffer, leaving 1 space at the beginning - // for a prefix we'll vary between the inline and non-inline keys. - char keyBuffer[kMaxKeyNameLength + 2] = { 0 }; - strncpy(keyBuffer + 1, name, kMaxKeyNameLength); - keyBuffer[0] = '1'; - m_inlineKey = v8::Persistent<v8::String>::New(v8::String::New(keyBuffer)); - keyBuffer[0] = '2'; - m_nonInlineKey = v8::Persistent<v8::String>::New(v8::String::New(keyBuffer)); -} - -V8EventListenerList::~V8EventListenerList() -{ - m_inlineKey.Dispose(); - m_nonInlineKey.Dispose(); -} - -V8EventListenerList::iterator V8EventListenerList::begin() -{ - return m_list.begin(); -} - -V8EventListenerList::iterator V8EventListenerList::end() -{ - return m_list.end(); -} - -v8::Handle<v8::String> V8EventListenerList::getKey(bool isInline) -{ - if (isInline) - return m_inlineKey; - else - return m_nonInlineKey; -} - -// See comment in .h file for this function, and update accordingly if -// implementation details change here. -void V8EventListenerList::add(V8EventListener* listener) -{ - m_list.append(listener); - - v8::HandleScope handleScope; - v8::Local<v8::Object> object = listener->getListenerObject(); - v8::Local<v8::Value> value = v8::External::Wrap(listener); - object->SetHiddenValue(getKey(listener->isInline()), value); -} - -void V8EventListenerList::remove(V8EventListener* listener) -{ - v8::HandleScope handleScope; - for (size_t i = 0; i < m_list.size(); i++) { - V8EventListener* element = m_list.at(i); - if (element->isInline() == listener->isInline() && element == listener) { - v8::Local<v8::Object> object = listener->getListenerObject(); - object->DeleteHiddenValue(getKey(listener->isInline())); - m_list.remove(i); - break; - } - } -} - -void V8EventListenerList::clear() -{ - v8::HandleScope handleScope; - for (size_t i = 0; i < m_list.size(); i++) { - V8EventListener* element = m_list.at(i); - v8::Local<v8::Object> object = element->getListenerObject(); - object->DeleteHiddenValue(getKey(element->isInline())); - } - m_list.clear(); -} - -V8EventListener* V8EventListenerList::find(v8::Local<v8::Object> object, bool isInline) -{ - v8::Local<v8::Value> value = object->GetHiddenValue(getKey(isInline)); - if (value.IsEmpty()) - return 0; - return reinterpret_cast<V8EventListener*>(v8::External::Unwrap(value)); -} - - // Static utility context. v8::Persistent<v8::Context> V8Proxy::m_utilityContext; @@ -350,6 +266,9 @@ SVG_POD_NATIVE_TYPES(MAKE_CASE) void V8Proxy::SetSVGContext(void* obj, SVGElement* context) { + if (obj == NULL) + return; + SVGElement* old_context = svg_object_to_context_map().get(obj); if (old_context == context) @@ -462,7 +381,7 @@ ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE) if (type == V8ClassIndex::MESSAGEPORT) { // Get the port and its entangled port. MessagePort* port1 = static_cast<MessagePort*>(obj); - MessagePort* port2 = port1->entangledPort(); + MessagePortProxy* port2 = port1->entangledPort(); if (port2 != NULL) { // As ports are always entangled in pairs only perform the entanglement // once for each pair (see ASSERT in MessagePort::unentangle()). @@ -561,10 +480,23 @@ ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE) Vector<v8::Persistent<v8::Value> > group; group.reserveCapacity(next_key_index - i); for (; i < next_key_index; ++i) { + Node* node = grouper[i].second; v8::Persistent<v8::Value> wrapper = - getDOMNodeMap().get(grouper[i].second); + getDOMNodeMap().get(node); if (!wrapper.IsEmpty()) group.append(wrapper); + // If the node is styled and there is a wrapper for the inline + // style declaration, we need to keep that style declaration + // wrapper alive as well, so we add it to the object group. + if (node->isStyledElement()) { + StyledElement* element = reinterpret_cast<StyledElement*>(node); + CSSStyleDeclaration* style = element->inlineStyleDecl(); + if (style != NULL) { + wrapper = getDOMObjectMap().get(style); + if (!wrapper.IsEmpty()) + group.append(wrapper); + } + } } if (group.size() > 1) @@ -713,7 +645,7 @@ void ConsoleMessageManager::ProcessDelayedMessages() // context. If that for some bizarre reason does not // exist, we clear the list of delayed messages to avoid // posting messages. We still deallocate the vector. - Frame* frame = V8Proxy::retrieveActiveFrame(); + Frame* frame = V8Proxy::retrieveFrameForEnteredContext(); Page* page = NULL; if (frame) page = frame->page(); @@ -754,7 +686,7 @@ static void HandleConsoleMessage(v8::Handle<v8::Message> message, v8::Handle<v8::Value> data) { // Use the frame where JavaScript is called from. - Frame* frame = V8Proxy::retrieveActiveFrame(); + Frame* frame = V8Proxy::retrieveFrameForEnteredContext(); if (!frame) return; @@ -791,7 +723,7 @@ static void ReportUnsafeAccessTo(Frame* target, DelayReporting delay) if (!targetDocument) return; - Frame* source = V8Proxy::retrieveActiveFrame(); + Frame* source = V8Proxy::retrieveFrameForEnteredContext(); if (!source || !source->document()) return; // Ignore error if the source document is gone. @@ -914,22 +846,6 @@ void V8Proxy::SetJSWrapperForDOMNode(Node* node, v8::Persistent<v8::Object> wrap getDOMNodeMap().set(node, wrapper); } -PassRefPtr<EventListener> V8Proxy::createInlineEventListener( - const String& functionName, - const String& code, Node* node) -{ - return V8LazyEventListener::create(m_frame, code, functionName); -} - -#if ENABLE(SVG) -PassRefPtr<EventListener> V8Proxy::createSVGEventHandler(const String& functionName, - const String& code, Node* node) -{ - return V8LazyEventListener::create(m_frame, code, functionName); -} -#endif - - // Event listeners static V8EventListener* FindEventListenerInList(V8EventListenerList& list, @@ -1081,10 +997,12 @@ bool V8Proxy::HandleOutOfMemory() Frame* frame = V8Proxy::retrieveFrame(context); V8Proxy* proxy = V8Proxy::retrieve(frame); - // Clean m_context, and event handlers. - proxy->clearForClose(); - // Destroy the global object. - proxy->DestroyGlobal(); + if (proxy != NULL) { + // Clean m_context, and event handlers. + proxy->clearForClose(); + // Destroy the global object. + proxy->DestroyGlobal(); + } #if PLATFORM(CHROMIUM) ChromiumBridge::notifyJSOutOfMemory(frame); @@ -1266,6 +1184,29 @@ v8::Local<v8::Value> V8Proxy::CallFunction(v8::Handle<v8::Function> function, } +v8::Local<v8::Value> V8Proxy::NewInstance(v8::Handle<v8::Function> constructor, + int argc, + v8::Handle<v8::Value> args[]) +{ + // No artificial limitations on the depth of recursion, see comment in + // V8Proxy::CallFunction. + v8::Local<v8::Value> result; + { + ConsoleMessageScope scope; + + // See comment in V8Proxy::CallFunction. + m_frame->keepAlive(); + + result = constructor->NewInstance(argc, args); + } + + if (v8::V8::IsDead()) + HandleFatalErrorInV8(); + + return result; +} + + v8::Local<v8::Function> V8Proxy::GetConstructor(V8ClassIndex::V8WrapperType t){ // A DOM constructor is a function instance created from a DOM constructor // template. There is one instance per context. A DOM constructor is @@ -1404,9 +1345,8 @@ v8::Persistent<v8::FunctionTemplate> V8Proxy::GetTemplate( V8ClassIndex::NODE); break; case V8ClassIndex::HTMLOPTIONSCOLLECTION: - setCollectionNamedGetter<HTMLOptionsCollection, Node>( - desc, - V8ClassIndex::NODE); + desc->InstanceTemplate()->SetNamedPropertyHandler( + USE_NAMED_PROPERTY_GETTER(HTMLCollection)); desc->InstanceTemplate()->SetIndexedPropertyHandler( USE_INDEXED_PROPERTY_GETTER(HTMLOptionsCollection), USE_INDEXED_PROPERTY_SETTER(HTMLOptionsCollection)); @@ -1415,12 +1355,7 @@ v8::Persistent<v8::FunctionTemplate> V8Proxy::GetTemplate( break; case V8ClassIndex::HTMLSELECTELEMENT: desc->InstanceTemplate()->SetNamedPropertyHandler( - nodeCollectionNamedPropertyGetter<HTMLSelectElement>, - 0, - 0, - 0, - 0, - v8::Integer::New(V8ClassIndex::NODE)); + USE_NAMED_PROPERTY_GETTER(HTMLSelectElementCollection)); desc->InstanceTemplate()->SetIndexedPropertyHandler( nodeCollectionIndexedPropertyGetter<HTMLSelectElement>, USE_INDEXED_PROPERTY_SETTER(HTMLSelectElementCollection), @@ -1673,6 +1608,12 @@ v8::Persistent<v8::FunctionTemplate> V8Proxy::GetTemplate( case V8ClassIndex::DOMPARSER: desc->SetCallHandler(USE_CALLBACK(DOMParserConstructor)); break; + case V8ClassIndex::HTMLIMAGEELEMENT: + desc->SetCallHandler(USE_CALLBACK(HTMLImageElementConstructor)); + break; + case V8ClassIndex::HTMLOPTIONELEMENT: + desc->SetCallHandler(USE_CALLBACK(HTMLOptionElementConstructor)); + break; case V8ClassIndex::WEBKITCSSMATRIX: desc->SetCallHandler(USE_CALLBACK(WebKitCSSMatrixConstructor)); break; @@ -1709,6 +1650,10 @@ v8::Persistent<v8::FunctionTemplate> V8Proxy::GetTemplate( desc->SetCallHandler(USE_CALLBACK(XSLTProcessorConstructor)); break; #endif + case V8ClassIndex::CLIENTRECTLIST: + desc->InstanceTemplate()->SetIndexedPropertyHandler( + USE_INDEXED_PROPERTY_GETTER(ClientRectList)); + break; default: break; } @@ -1754,7 +1699,7 @@ Frame* V8Proxy::retrieveFrame(v8::Handle<v8::Context> context) } -Frame* V8Proxy::retrieveActiveFrame() +Frame* V8Proxy::retrieveFrameForEnteredContext() { v8::Handle<v8::Context> context = v8::Context::GetEntered(); if (context.IsEmpty()) @@ -1763,6 +1708,24 @@ Frame* V8Proxy::retrieveActiveFrame() } +Frame* V8Proxy::retrieveFrameForCurrentContext() +{ + v8::Handle<v8::Context> context = v8::Context::GetCurrent(); + if (context.IsEmpty()) + return 0; + return retrieveFrame(context); +} + + +Frame* V8Proxy::retrieveFrameForCallingContext() +{ + v8::Handle<v8::Context> context = v8::Context::GetCalling(); + if (context.IsEmpty()) + return 0; + return retrieveFrame(context); +} + + Frame* V8Proxy::retrieveFrame() { DOMWindow* window = retrieveWindow(); @@ -1876,6 +1839,24 @@ void V8Proxy::ClearDocumentWrapper() } +void V8Proxy::UpdateDocumentWrapperCache() +{ + v8::HandleScope handle_scope; + v8::Context::Scope context_scope(GetContext()); + v8::Handle<v8::Value> document_wrapper = NodeToV8Object(m_frame->document()); + m_context->Global()->ForceSet(v8::String::New("document"), + document_wrapper, + 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_context.Dispose(); @@ -1912,21 +1893,26 @@ void V8Proxy::clearForClose() void V8Proxy::clearForNavigation() { + // disconnect all event listeners + DisconnectEventListeners(); + if (!m_context.IsEmpty()) { v8::HandleScope handle; ClearDocumentWrapper(); v8::Context::Scope context_scope(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 = LookupDOMWrapper(V8ClassIndex::DOMWINDOW, m_global); ASSERT(!wrapper.IsEmpty()); wrapper->TurnOnAccessCheck(); - // disconnect all event listeners - DisconnectEventListeners(); - // Separate the context from its global object. m_context->DetachGlobal(); @@ -1985,10 +1971,10 @@ void V8Proxy::updateDocument() return; } - { - v8::HandleScope scope; - SetSecurityToken(); - } + // We have a new document and we need to update the cache. + UpdateDocumentWrapperCache(); + + updateSecurityOrigin(); } void V8Proxy::updateSecurityOrigin() @@ -2036,18 +2022,11 @@ bool V8Proxy::CanAccessPrivate(DOMWindow* target_window) if (!origin_window) return false; - // JS may be attempting to access the "window" object, which should be - // valid, even if the document hasn't been constructed yet. - // If the document doesn't exist yet allow JS to access the window object. - if (!origin_window->document()) - return true; - const SecurityOrigin* active_security_origin = origin_window->securityOrigin(); const SecurityOrigin* target_security_origin = target_window->securityOrigin(); // We have seen crashes were the security origin of the target has not been // initialized. Defend against that. - ASSERT(target_security_origin); if (!target_security_origin) return false; @@ -2115,8 +2094,12 @@ v8::Persistent<v8::Context> V8Proxy::createNewContext( int index = 0; for (V8ExtensionList::iterator it = m_extensions.begin(); it != m_extensions.end(); ++it) { + // 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 (it->scheme.length() > 0 && - it->scheme != m_frame->document()->url().protocol()) + (it->scheme != m_frame->loader()->activeDocumentLoader()->url().protocol() || + it->scheme != m_frame->page()->mainFrame()->loader()->activeDocumentLoader()->url().protocol())) continue; extensionNames[index++] = it->extension->name(); @@ -2269,6 +2252,8 @@ void V8Proxy::InitContextIfNeeded() v8::Handle<v8::Object> v8_global = context->Global(); v8_global->Set(implicit_proto_string, js_window); + updateDocument(); + SetSecurityToken(); m_frame->loader()->dispatchWindowObjectAvailable(); @@ -2417,13 +2402,17 @@ v8::Handle<v8::Value> V8Proxy::ToV8Object(V8ClassIndex::V8WrapperType type, void else SetJSWrapperForDOMObject(imp, result); - // Special case for non-node objects History, Location and - // Navigator. Both Safari and FF let Location and Navigator JS - // wrappers survive GC. To mimic their behaviors, V8 creates + // Special case for non-node objects associated with a + // DOMWindow. Both Safari and FF let the JS wrappers for these + // objects survive GC. To mimic their behavior, V8 creates // hidden references from the DOMWindow to these wrapper // objects. These references get cleared when the DOMWindow is // reused by a new page. switch (type) { + case V8ClassIndex::CONSOLE: + SetHiddenWindowReference(static_cast<Console*>(imp)->frame(), + V8Custom::kDOMWindowConsoleIndex, result); + break; case V8ClassIndex::HISTORY: SetHiddenWindowReference(static_cast<History*>(imp)->frame(), V8Custom::kDOMWindowHistoryIndex, result); @@ -2432,10 +2421,43 @@ v8::Handle<v8::Value> V8Proxy::ToV8Object(V8ClassIndex::V8WrapperType type, void SetHiddenWindowReference(static_cast<Navigator*>(imp)->frame(), V8Custom::kDOMWindowNavigatorIndex, result); break; + case V8ClassIndex::SCREEN: + SetHiddenWindowReference(static_cast<Screen*>(imp)->frame(), + V8Custom::kDOMWindowScreenIndex, result); + break; case V8ClassIndex::LOCATION: SetHiddenWindowReference(static_cast<Location*>(imp)->frame(), V8Custom::kDOMWindowLocationIndex, result); break; + case V8ClassIndex::DOMSELECTION: + SetHiddenWindowReference(static_cast<DOMSelection*>(imp)->frame(), + V8Custom::kDOMWindowDOMSelectionIndex, result); + break; + case V8ClassIndex::BARINFO: { + BarInfo* barinfo = static_cast<BarInfo*>(imp); + Frame* frame = barinfo->frame(); + switch (barinfo->type()) { + case BarInfo::Locationbar: + SetHiddenWindowReference(frame, V8Custom::kDOMWindowLocationbarIndex, result); + break; + case BarInfo::Menubar: + SetHiddenWindowReference(frame, V8Custom::kDOMWindowMenubarIndex, result); + break; + case BarInfo::Personalbar: + SetHiddenWindowReference(frame, V8Custom::kDOMWindowPersonalbarIndex, result); + break; + case BarInfo::Scrollbars: + SetHiddenWindowReference(frame, V8Custom::kDOMWindowScrollbarsIndex, result); + break; + case BarInfo::Statusbar: + SetHiddenWindowReference(frame, V8Custom::kDOMWindowStatusbarIndex, result); + break; + case BarInfo::Toolbar: + SetHiddenWindowReference(frame, V8Custom::kDOMWindowToolbarIndex, result); + break; + } + break; + } default: break; } @@ -2506,6 +2528,15 @@ void* V8Proxy::ToNativeObjectImpl(V8ClassIndex::V8WrapperType type, return DOMWrapperToNative<void>(object); } + +void* V8Proxy::ToSVGPODTypeImpl(V8ClassIndex::V8WrapperType type, + v8::Handle<v8::Value> object) { + return IsWrapperOfType(object, type) + ? DOMWrapperToNative<void>(object) + : NULL; +} + + v8::Handle<v8::Object> V8Proxy::LookupDOMWrapper( V8ClassIndex::V8WrapperType type, v8::Handle<v8::Value> value) { @@ -2524,6 +2555,20 @@ v8::Handle<v8::Object> V8Proxy::LookupDOMWrapper( } +// static +void* V8Proxy::DOMWrapperToNodeHelper(v8::Handle<v8::Value> value) { + ASSERT(MaybeDOMWrapper(value)); + + v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); + + ASSERT(GetDOMWrapperType(object) == V8ClassIndex::NODE); + + v8::Handle<v8::Value> wrapper = + object->GetInternalField(V8Custom::kDOMWrapperObjectIndex); + return ExtractCPointer<Node>(wrapper); +} + + PassRefPtr<NodeFilter> V8Proxy::ToNativeNodeFilter(v8::Handle<v8::Value> filter) { // A NodeFilter is used when walking through a DOM tree or iterating tree @@ -2549,7 +2594,7 @@ v8::Local<v8::Object> V8Proxy::InstantiateV8Object( { // Make a special case for document.all if (desc_type == V8ClassIndex::HTMLCOLLECTION && - static_cast<HTMLCollection*>(imp)->type() == HTMLCollection::DocAll) { + static_cast<HTMLCollection*>(imp)->type() == DocAll) { desc_type = V8ClassIndex::UNDETECTABLEHTMLCOLLECTION; } @@ -2936,6 +2981,19 @@ v8::Handle<v8::Value> V8Proxy::NodeToV8Object(Node* node) { if (!node) return v8::Null(); + // Find the context to which the node belongs and create the wrapper + // in that context. If the node is not in a document, the current + // context is used. + // + // Getting the context might initialize the context which can instantiate + // a document wrapper. Therefore, we get the context before checking if + // the node already has a wrapper. + v8::Local<v8::Context> context; + Document* doc = node->document(); + if (doc) { + context = V8Proxy::GetContext(doc->frame()); + } + v8::Handle<v8::Object> wrapper = getDOMNodeMap().get(node); if (!wrapper.IsEmpty()) return wrapper; @@ -3001,14 +3059,7 @@ v8::Handle<v8::Value> V8Proxy::NodeToV8Object(Node* node) type = V8ClassIndex::NODE; } - // Find the context to which the node belongs and create the wrapper - // in that context. If the node is not in a document, the current - // context is used. - v8::Local<v8::Context> context; - Document* doc = node->document(); - if (doc) { - context = V8Proxy::GetContext(doc->frame()); - } + // Enter the node's context and create the wrapper in that context. if (!context.IsEmpty()) { context->Enter(); } @@ -3055,8 +3106,8 @@ v8::Handle<v8::Value> V8Proxy::NodeToV8Object(Node* node) // A JS object of type EventTarget can only be the following possible types: -// 1) EventTargetNode; 2) XMLHttpRequest; 3) MessagePort; 4) SVGElementInstance; -// 5) XMLHttpRequestUpload 6) Worker +// 1) EventTargetNode; 2) DOMWindow 3) XMLHttpRequest; 4) MessagePort; +// 5) XMLHttpRequestUpload // check EventTarget.h for new type conversion methods v8::Handle<v8::Value> V8Proxy::EventTargetToV8Object(EventTarget* target) { @@ -3085,6 +3136,9 @@ v8::Handle<v8::Value> V8Proxy::EventTargetToV8Object(EventTarget* target) if (node) return NodeToV8Object(node); + if (DOMWindow* domWindow = target->toDOMWindow()) + return ToV8Object(V8ClassIndex::DOMWINDOW, domWindow); + // XMLHttpRequest is created within its JS counterpart. XMLHttpRequest* xhr = target->toXMLHttpRequest(); if (xhr) { @@ -3273,7 +3327,7 @@ v8::Handle<v8::Value> V8Proxy::WindowToV8Object(DOMWindow* window) return v8::Handle<v8::Object>(); // Special case: Because of evaluateInNewContext() one DOMWindow can have - // multipe contexts and multiple global objects associated with it. When + // 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 // necessarily the first global object associated with that DOMWindow. diff --git a/V8Binding/binding/v8_proxy.h b/V8Binding/binding/v8_proxy.h index 17a2d1b..a9f871e 100644 --- a/V8Binding/binding/v8_proxy.h +++ b/V8Binding/binding/v8_proxy.h @@ -15,6 +15,7 @@ #include "ScriptSourceCode.h" // for WebCore::ScriptSourceCode #include "SecurityOrigin.h" // for WebCore::SecurityOrigin #include "V8DOMMap.h" +#include "V8EventListenerList.h" #include <wtf/Assertions.h> #include <wtf/PassRefPtr.h> // so generated bindings don't have to #include <wtf/Vector.h> @@ -32,6 +33,7 @@ namespace WebCore { class CSSStyleDeclaration; +class ClientRectList; class DOMImplementation; class Element; class Event; @@ -74,35 +76,6 @@ class SVGElementInstance; class V8EventListener; class V8ObjectEventListener; -// This is a container for V8EventListener objects that also does some -// caching to speed up finding entries by v8::Object. -class V8EventListenerList { - public: - static const size_t kMaxKeyNameLength = 254; - // The name should be distinct from any other V8EventListenerList - // within the same process, and <= kMaxKeyNameLength characters. - explicit V8EventListenerList(const char* name); - ~V8EventListenerList(); - - typedef Vector<V8EventListener*>::iterator iterator; - V8EventListenerList::iterator begin(); - iterator end(); - - // In addition to adding the listener to this list, this also caches the - // V8EventListener as a hidden property on its wrapped v8 listener object, - // so we can quickly look it up later. - void add(V8EventListener*); - void remove(V8EventListener*); - V8EventListener* find(v8::Local<v8::Object>, bool isInline); - void clear(); - - private: - v8::Handle<v8::String> getKey(bool isInline); - v8::Persistent<v8::String> m_inlineKey; - v8::Persistent<v8::String> m_nonInlineKey; - Vector<V8EventListener*> m_list; -}; - // TODO(fqian): use standard logging facilities in WebCore. void log_info(Frame* frame, const String& msg, const String& url); @@ -196,8 +169,7 @@ class V8Proxy { }; explicit V8Proxy(Frame* frame) - : m_frame(frame), m_event_listeners("m_event_listeners"), - m_xhr_listeners("m_xhr_listeners"), m_inlineCode(false), + : m_frame(frame), m_inlineCode(false), m_timerCallback(false), m_recursion(0) { } ~V8Proxy(); @@ -254,13 +226,7 @@ class V8Proxy { static void GCProtect(void* dom_object); static void GCUnprotect(void* dom_object); - // Create a lazy event listener. - PassRefPtr<EventListener> createInlineEventListener( - const String& functionName, const String& code, Node* node); #if ENABLE(SVG) - PassRefPtr<EventListener> createSVGEventHandler( - const String& functionName, const String& code, Node* node); - static void SetSVGContext(void* object, SVGElement* context); static SVGElement* GetSVGContext(void* object); #endif @@ -289,6 +255,11 @@ class V8Proxy { int argc, v8::Handle<v8::Value> argv[]); + // Call the function as constructor with the given arguments. + v8::Local<v8::Value> NewInstance(v8::Handle<v8::Function> constructor, + int argc, + v8::Handle<v8::Value> argv[]); + // Returns the dom constructor function for the given node type. v8::Local<v8::Function> GetConstructor(V8ClassIndex::V8WrapperType type); @@ -314,10 +285,39 @@ class V8Proxy { // Returns the frame object of the window object associated with // a context. static Frame* retrieveFrame(v8::Handle<v8::Context> context); - // Returns the frame that started JS execution. - // NOTE: cannot declare retrieveActiveFrame as inline function, - // VS complains at linking time. - static Frame* retrieveActiveFrame(); + + + // The three functions below retrieve WebFrame instances relating the + // currently executing JavaScript. Since JavaScript can make function calls + // across frames, though, we need to be more precise. + // + // For example, imagine that a JS function in frame A calls a function in + // frame B, which calls native code, which wants to know what the 'active' + // frame is. + // + // The 'entered context' is the context where execution first entered the + // script engine; the context that is at the bottom of the JS function stack. + // RetrieveFrameForEnteredContext() would return Frame A in our example. + // This frame is often referred to as the "dynamic global object." + // + // The 'current context' is the context the JS engine is currently inside of; + // the context that is at the top of the JS function stack. + // RetrieveFrameForCurrentContext() would return Frame B in our example. + // This frame is often referred to as the "lexical global object." + // + // Finally, the 'calling context' is the context one below the current + // context on the JS function stack. For example, if function f calls + // function g, then the calling context will be the context associated with + // f. This context is commonly used by DOM security checks because they want + // to know who called them. + // + // If you are unsure which of these functions to use, ask abarth. + // + // NOTE: These cannot be declared as inline function, because VS complains at + // linking time. + static Frame* retrieveFrameForEnteredContext(); + static Frame* retrieveFrameForCurrentContext(); + static Frame* retrieveFrameForCallingContext(); // Returns V8 Context of a frame. If none exists, creates // a new context. It is potentially slow and consumes memory. @@ -379,17 +379,11 @@ class V8Proxy { // A help function extract a node type pointer from a DOM wrapper. // Wrapped pointer must be cast to Node* first. + static void* DOMWrapperToNodeHelper(v8::Handle<v8::Value> value); + template <class C> static C* DOMWrapperToNode(v8::Handle<v8::Value> value) { - ASSERT(MaybeDOMWrapper(value)); - - v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); - - ASSERT(GetDOMWrapperType(object) == V8ClassIndex::NODE); - - v8::Handle<v8::Value> wrapper = - object->GetInternalField(V8Custom::kDOMWrapperObjectIndex); - return static_cast<C*>(ExtractCPointer<Node>(wrapper)); + return static_cast<C*>(DOMWrapperToNodeHelper(value)); } template<typename T> @@ -495,6 +489,9 @@ class V8Proxy { static void RegisterExtension(v8::Extension* extension, const String& schemeRestriction); + static void* ToSVGPODTypeImpl(V8ClassIndex::V8WrapperType type, + v8::Handle<v8::Value> object); + private: v8::Persistent<v8::Context> createNewContext(v8::Handle<v8::Object> global); void InitContextIfNeeded(); @@ -502,6 +499,14 @@ class V8Proxy { void SetSecurityToken(); void ClearDocumentWrapper(); void UpdateDocumentWrapper(v8::Handle<v8::Value> wrapper); + + // 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(); + // Dispose global handles of m_contexts and friends. void DisposeContextHandles(); diff --git a/V8Binding/binding/v8_utility.h b/V8Binding/binding/v8_utility.h new file mode 100644 index 0000000..a7c3325 --- /dev/null +++ b/V8Binding/binding/v8_utility.h @@ -0,0 +1,68 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef V8_UTILITY_H__ +#define V8_UTILITY_H__ + +#include "V8Utilities.h" + +// To break a cycle dependency during upstreaming this block of code, +// ifdefing it out based on this #define. +// +// TODO(ajwong): After https://bugs.webkit.org/show_bug.cgi?id=25595 +// lands and is rolled down into chromium, migrate all headaers to use +// the code in V8Utilities.h directly, and then, remove this code. +#ifndef V8UTILITIES_DEFINED +namespace WebCore { + +class AllowAllocation { + public: + inline AllowAllocation() { + m_prev = m_current; + m_current = true; + } + inline ~AllowAllocation() { + m_current = m_prev; + } + static bool m_current; + private: + bool m_prev; +}; + +class SafeAllocation { + public: + static inline v8::Local<v8::Object> NewInstance( + v8::Handle<v8::Function> fun); + static inline v8::Local<v8::Object> NewInstance( + v8::Handle<v8::ObjectTemplate> templ); + static inline v8::Local<v8::Object> NewInstance( + v8::Handle<v8::Function> fun, int argc, v8::Handle<v8::Value> argv[]); +}; + +v8::Local<v8::Object> SafeAllocation::NewInstance( + v8::Handle<v8::Function> fun) { + if (fun.IsEmpty()) + return v8::Local<v8::Object>(); + AllowAllocation allow; + return fun->NewInstance(); +} + +v8::Local<v8::Object> SafeAllocation::NewInstance( + v8::Handle<v8::ObjectTemplate> templ) { + if (templ.IsEmpty()) return v8::Local<v8::Object>(); + AllowAllocation allow; + return templ->NewInstance(); +} + +v8::Local<v8::Object> SafeAllocation::NewInstance( + v8::Handle<v8::Function> fun, int argc, v8::Handle<v8::Value> argv[]) { + if (fun.IsEmpty()) return v8::Local<v8::Object>(); + AllowAllocation allow; + return fun->NewInstance(argc, argv); +} + +} // namespace WebCore +#endif // V8UTILITIES_DEFINED + +#endif // V8_UTILITY_H__ |