diff options
Diffstat (limited to 'Source/WebCore/bindings')
108 files changed, 2216 insertions, 1246 deletions
diff --git a/Source/WebCore/bindings/ScriptControllerBase.cpp b/Source/WebCore/bindings/ScriptControllerBase.cpp index fbf6d3e..5e87dbf 100644 --- a/Source/WebCore/bindings/ScriptControllerBase.cpp +++ b/Source/WebCore/bindings/ScriptControllerBase.cpp @@ -21,6 +21,7 @@ #include "config.h" #include "ScriptController.h" +#include "ContentSecurityPolicy.h" #include "DocumentLoader.h" #include "Frame.h" #include "FrameLoaderClient.h" diff --git a/Source/WebCore/bindings/generic/RuntimeEnabledFeatures.cpp b/Source/WebCore/bindings/generic/RuntimeEnabledFeatures.cpp index 14e4ac8..e9591fd 100644 --- a/Source/WebCore/bindings/generic/RuntimeEnabledFeatures.cpp +++ b/Source/WebCore/bindings/generic/RuntimeEnabledFeatures.cpp @@ -46,16 +46,20 @@ bool RuntimeEnabledFeatures::isLocalStorageEnabled = true; bool RuntimeEnabledFeatures::isSessionStorageEnabled = true; bool RuntimeEnabledFeatures::isWebkitNotificationsEnabled = false; bool RuntimeEnabledFeatures::isApplicationCacheEnabled = true; +bool RuntimeEnabledFeatures::isDataTransferItemsEnabled = true; bool RuntimeEnabledFeatures::isGeolocationEnabled = true; bool RuntimeEnabledFeatures::isIndexedDBEnabled = false; bool RuntimeEnabledFeatures::isWebAudioEnabled = false; -bool RuntimeEnabledFeatures::isWebGLEnabled = false; bool RuntimeEnabledFeatures::isPushStateEnabled = false; bool RuntimeEnabledFeatures::isTouchEnabled = true; bool RuntimeEnabledFeatures::isDeviceMotionEnabled = true; bool RuntimeEnabledFeatures::isDeviceOrientationEnabled = true; bool RuntimeEnabledFeatures::isSpeechInputEnabled = true; +#if ENABLE(MEDIA_STREAM) +bool RuntimeEnabledFeatures::isMediaStreamEnabled = true; +#endif + #if ENABLE(XHR_RESPONSE_BLOB) bool RuntimeEnabledFeatures::isXHRResponseBlobEnabled = false; #endif diff --git a/Source/WebCore/bindings/generic/RuntimeEnabledFeatures.h b/Source/WebCore/bindings/generic/RuntimeEnabledFeatures.h index 7e21214..1004ea4 100644 --- a/Source/WebCore/bindings/generic/RuntimeEnabledFeatures.h +++ b/Source/WebCore/bindings/generic/RuntimeEnabledFeatures.h @@ -51,6 +51,9 @@ public: static void setApplicationCacheEnabled(bool isEnabled) { isApplicationCacheEnabled = isEnabled; } static bool applicationCacheEnabled() { return isApplicationCacheEnabled; } + static void setDataTransferItemsEnabled(bool isEnabled) { isDataTransferItemsEnabled = isEnabled; } + static bool dataTransferItemsEnabled() { return isDataTransferItemsEnabled; } + static void setGeolocationEnabled(bool isEnabled) { isGeolocationEnabled = isEnabled; } static bool geolocationEnabled() { return isGeolocationEnabled; } @@ -94,27 +97,6 @@ public: static bool webkitAudioContextEnabled() { return isWebAudioEnabled; } #endif -#if ENABLE(WEBGL) || ENABLE(BLOB) - static void setWebGLEnabled(bool isEnabled) { isWebGLEnabled = isEnabled; } - static bool webGLRenderingContextEnabled() { return isWebGLEnabled; } - static bool webGLArrayBufferEnabled() { return isWebGLEnabled; } - static bool webGLByteArrayEnabled() { return isWebGLEnabled; } - static bool webGLUnsignedByteArrayEnabled() { return isWebGLEnabled; } - static bool webGLShortArrayEnabled() { return isWebGLEnabled; } - static bool webGLUnsignedShortArrayEnabled() { return isWebGLEnabled; } - static bool webGLIntArrayEnabled() { return isWebGLEnabled; } - static bool webGLUnsignedIntArrayEnabled() { return isWebGLEnabled; } - static bool webGLFloatArrayEnabled() { return isWebGLEnabled; } - static bool webGLActiveInfoEnabled() { return isWebGLEnabled; } - static bool webGLBufferEnabled() { return isWebGLEnabled; } - static bool webGLFramebufferEnabled() { return isWebGLEnabled; } - static bool webGLProgramEnabled() { return isWebGLEnabled; } - static bool webGLRenderbufferEnabled() { return isWebGLEnabled; } - static bool webGLShaderEnabled() { return isWebGLEnabled; } - static bool webGLTextureEnabled() { return isWebGLEnabled; } - static bool webGLUniformLocationEnabled() { return isWebGLEnabled; } -#endif - static void setPushStateEnabled(bool isEnabled) { isPushStateEnabled = isEnabled; } static bool pushStateEnabled() { return isPushStateEnabled; } static bool replaceStateEnabled() { return isPushStateEnabled; } @@ -162,6 +144,12 @@ public: static void setJavaScriptI18NAPIEnabled(bool isEnabled) { isJavaScriptI18NAPIEnabled = isEnabled; } #endif +#if ENABLE(MEDIA_STREAM) + static bool mediaStreamEnabled() { return isMediaStreamEnabled; } + static void setMediaStreamEnabled(bool isEnabled) { isMediaStreamEnabled = isEnabled; } + static bool webkitGetUserMediaEnabled() { return isMediaStreamEnabled; } +#endif + private: // Never instantiate. RuntimeEnabledFeatures() { } @@ -170,10 +158,10 @@ private: static bool isSessionStorageEnabled; static bool isWebkitNotificationsEnabled; static bool isApplicationCacheEnabled; + static bool isDataTransferItemsEnabled; static bool isGeolocationEnabled; static bool isIndexedDBEnabled; static bool isWebAudioEnabled; - static bool isWebGLEnabled; static bool isPushStateEnabled; static bool isTouchEnabled; static bool isDeviceMotionEnabled; @@ -190,6 +178,10 @@ private: #if ENABLE(JAVASCRIPT_I18N_API) static bool isJavaScriptI18NAPIEnabled; #endif + +#if ENABLE(MEDIA_STREAM) + static bool isMediaStreamEnabled; +#endif }; } // namespace WebCore diff --git a/Source/WebCore/bindings/gobject/GNUmakefile.am b/Source/WebCore/bindings/gobject/GNUmakefile.am index 881f45a..8370b86 100644 --- a/Source/WebCore/bindings/gobject/GNUmakefile.am +++ b/Source/WebCore/bindings/gobject/GNUmakefile.am @@ -244,6 +244,8 @@ webkitgtk_gdom_built_sources += \ DerivedSources/webkit/WebKitDOMUIEventPrivate.h \ DerivedSources/webkit/WebKitDOMValidityState.cpp \ DerivedSources/webkit/WebKitDOMValidityStatePrivate.h \ + DerivedSources/webkit/WebKitDOMWebKitAnimation.cpp \ + DerivedSources/webkit/WebKitDOMWebKitAnimationList.cpp \ DerivedSources/webkit/WebKitDOMWebKitPoint.cpp \ DerivedSources/webkit/WebKitDOMWebKitPointPrivate.h \ DerivedSources/webkit/WebKitDOMXPathExpression.cpp \ @@ -372,6 +374,8 @@ webkitgtk_built_h_api += \ DerivedSources/webkit/WebKitDOMObject.h \ DerivedSources/webkit/WebKitDOMNavigator.h \ DerivedSources/webkit/WebKitDOMScreen.h \ + DerivedSources/webkit/WebKitDOMWebKitAnimation.h \ + DerivedSources/webkit/WebKitDOMWebKitAnimationList.h \ DerivedSources/webkit/WebKitDOMWebKitPoint.h \ DerivedSources/webkit/WebKitDOMDOMMimeType.h \ DerivedSources/webkit/WebKitDOMDOMMimeTypeArray.h \ diff --git a/Source/WebCore/bindings/gobject/GObjectEventListener.cpp b/Source/WebCore/bindings/gobject/GObjectEventListener.cpp index 27432b9..6211e7d 100644 --- a/Source/WebCore/bindings/gobject/GObjectEventListener.cpp +++ b/Source/WebCore/bindings/gobject/GObjectEventListener.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Igalia S.L. + * Copyright (C) 2010, 2011 Igalia S.L. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -29,55 +29,51 @@ namespace WebCore { -GObjectEventListener::GObjectEventListener(GObject* object, DOMWindow* window, Node* node, const char* domEventName, const char* signalName) +typedef void (*GObjectEventListenerCallback)(GObject*, WebKitDOMEvent*, void*); + +GObjectEventListener::GObjectEventListener(GObject* object, EventTarget* target, const char* domEventName, GCallback handler, bool capture, void* userData) : EventListener(GObjectEventListenerType) , m_object(object) - , m_coreNode(node) - , m_coreWindow(window) + , m_coreTarget(target) , m_domEventName(domEventName) - , m_signalName(signalName) + , m_handler(handler) + , m_capture(capture) + , m_userData(userData) { - ASSERT(!m_coreWindow || !m_coreNode); - + ASSERT(m_coreTarget); g_object_weak_ref(object, reinterpret_cast<GWeakNotify>(GObjectEventListener::gobjectDestroyedCallback), this); } GObjectEventListener::~GObjectEventListener() { - if (!m_coreWindow && !m_coreNode) + if (!m_coreTarget) return; g_object_weak_unref(m_object, reinterpret_cast<GWeakNotify>(GObjectEventListener::gobjectDestroyedCallback), this); } void GObjectEventListener::gobjectDestroyed() { - ASSERT(!m_coreWindow || !m_coreNode); - - // We must set m_coreWindow and m_coreNode to null, because removeEventListener may call the - // destructor as a side effect and we must be in the proper state to prevent g_object_weak_unref. - if (DOMWindow* window = m_coreWindow) { - m_coreWindow = 0; - window->removeEventListener(m_domEventName.data(), this, false); - return; - } + ASSERT(m_coreTarget); - Node* node = m_coreNode; - m_coreNode = 0; // See above. - node->removeEventListener(m_domEventName.data(), this, false); + // We must set m_coreTarget to null, because removeEventListener + // may call the destructor as a side effect and we must be in the + // proper state to prevent g_object_weak_unref. + EventTarget* target = m_coreTarget; + m_coreTarget = 0; + target->removeEventListener(m_domEventName.data(), this, m_capture); } void GObjectEventListener::handleEvent(ScriptExecutionContext*, Event* event) { - gboolean handled = FALSE; WebKitDOMEvent* gobjectEvent = WEBKIT_DOM_EVENT(WebKit::kit(event)); - g_signal_emit_by_name(m_object, m_signalName.data(), gobjectEvent, &handled); + reinterpret_cast<GObjectEventListenerCallback>(m_handler)(m_object, gobjectEvent, m_userData); g_object_unref(gobjectEvent); } bool GObjectEventListener::operator==(const EventListener& listener) { if (const GObjectEventListener* gobjectEventListener = GObjectEventListener::cast(&listener)) - return m_signalName == gobjectEventListener->m_signalName && m_object == gobjectEventListener->m_object; + return m_object == gobjectEventListener->m_object && m_handler == gobjectEventListener->m_handler; return false; } diff --git a/Source/WebCore/bindings/gobject/GObjectEventListener.h b/Source/WebCore/bindings/gobject/GObjectEventListener.h index ef1637a..6c85701 100644 --- a/Source/WebCore/bindings/gobject/GObjectEventListener.h +++ b/Source/WebCore/bindings/gobject/GObjectEventListener.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Igalia S.L. + * Copyright (C) 2010, 2011 Igalia S.L. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,30 +19,30 @@ #ifndef GObjectEventListener_h #define GObjectEventListener_h -#include "DOMWindow.h" #include "EventListener.h" -#include "Node.h" +#include "EventTarget.h" #include <wtf/RefPtr.h> #include <wtf/text/CString.h> typedef struct _GObject GObject; +typedef void (*GCallback) (void); namespace WebCore { class GObjectEventListener : public EventListener { public: - static void addEventListener(GObject* object, DOMWindow* window, const char* domEventName, const char* signalName) + static bool addEventListener(GObject* object, EventTarget* target, const char* domEventName, GCallback handler, bool useCapture, void* userData) { - RefPtr<GObjectEventListener> listener(adoptRef(new GObjectEventListener(object, window, 0, domEventName, signalName))); - window->addEventListener(domEventName, listener.release(), false); + RefPtr<GObjectEventListener> listener(adoptRef(new GObjectEventListener(object, target, domEventName, handler, useCapture, userData))); + return target->addEventListener(domEventName, listener.release(), useCapture); } - static void addEventListener(GObject* object, Node* node, const char* domEventName, const char* signalName) + static bool removeEventListener(GObject* object, EventTarget* target, const char* domEventName, GCallback handler, bool useCapture) { - RefPtr<GObjectEventListener> listener(adoptRef(new GObjectEventListener(object, 0, node, domEventName, signalName))); - node->addEventListener(domEventName, listener.release(), false); + GObjectEventListener key(object, target, domEventName, handler, useCapture, 0); + return target->removeEventListener(domEventName, &key, useCapture); } static void gobjectDestroyedCallback(GObjectEventListener* listener, GObject*) @@ -60,7 +60,7 @@ public: virtual bool operator==(const EventListener& other); private: - GObjectEventListener(GObject*, DOMWindow*, Node*, const char* domEventName, const char* signalName); + GObjectEventListener(GObject*, EventTarget*, const char* domEventName, GCallback handler, bool capture, void* userData); ~GObjectEventListener(); void gobjectDestroyed(); @@ -68,12 +68,13 @@ private: GObject* m_object; - // We do not need to keep a reference to these WebCore objects, because - // we only use them when the GObject and thus the WebCore object is alive. - Node* m_coreNode; - DOMWindow* m_coreWindow; + // We do not need to keep a reference to the m_coreTarget, because + // we only use it when the GObject and thus the m_coreTarget object is alive. + EventTarget* m_coreTarget; CString m_domEventName; - CString m_signalName; + GCallback m_handler; + bool m_capture; + void* m_userData; }; } // namespace WebCore diff --git a/Source/WebCore/bindings/gobject/WebKitDOMEventTarget.cpp b/Source/WebCore/bindings/gobject/WebKitDOMEventTarget.cpp index f2b1a94..f74c340 100644 --- a/Source/WebCore/bindings/gobject/WebKitDOMEventTarget.cpp +++ b/Source/WebCore/bindings/gobject/WebKitDOMEventTarget.cpp @@ -66,17 +66,42 @@ static void webkit_dom_event_target_default_init(WebKitDOMEventTargetIface*) void webkit_dom_event_target_dispatch_event(WebKitDOMEventTarget* target, WebKitDOMEvent* event, GError** error) { - WebKitDOMEventTargetIface* iface; - g_return_if_fail(WEBKIT_DOM_IS_EVENT_TARGET(target)); g_return_if_fail(WEBKIT_DOM_IS_EVENT(event)); - iface = WEBKIT_DOM_EVENT_TARGET_GET_IFACE(target); + WebKitDOMEventTargetIface* iface = WEBKIT_DOM_EVENT_TARGET_GET_IFACE(target); if (iface->dispatch_event) iface->dispatch_event(target, event, error); } +gboolean webkit_dom_event_target_add_event_listener(WebKitDOMEventTarget* target, const char* eventName, GCallback handler, gboolean bubble, gpointer userData) +{ + + g_return_val_if_fail(WEBKIT_DOM_IS_EVENT_TARGET(target), FALSE); + g_return_val_if_fail(eventName, FALSE); + + WebKitDOMEventTargetIface* iface = WEBKIT_DOM_EVENT_TARGET_GET_IFACE(target); + + if (iface->add_event_listener) + return iface->add_event_listener(target, eventName, handler, bubble, userData); + + return FALSE; +} + +gboolean webkit_dom_event_target_remove_event_listener(WebKitDOMEventTarget* target, const char* eventName, GCallback handler, gboolean bubble) +{ + g_return_val_if_fail(WEBKIT_DOM_IS_EVENT_TARGET(target), FALSE); + g_return_val_if_fail(eventName, FALSE); + + WebKitDOMEventTargetIface* iface = WEBKIT_DOM_EVENT_TARGET_GET_IFACE(target); + + if (iface->remove_event_listener) + return iface->remove_event_listener(target, eventName, handler, bubble); + + return FALSE; +} + namespace WebKit { WebCore::EventTarget* core(WebKitDOMEventTarget* request) diff --git a/Source/WebCore/bindings/gobject/WebKitDOMEventTarget.h b/Source/WebCore/bindings/gobject/WebKitDOMEventTarget.h index 206abc7..4adbda1 100644 --- a/Source/WebCore/bindings/gobject/WebKitDOMEventTarget.h +++ b/Source/WebCore/bindings/gobject/WebKitDOMEventTarget.h @@ -37,9 +37,19 @@ struct _WebKitDOMEventTargetIface { GTypeInterface gIface; /* virtual table */ - void (* dispatch_event)(WebKitDOMEventTarget* target, - WebKitDOMEvent* event, - GError** error); + void (* dispatch_event)(WebKitDOMEventTarget *target, + WebKitDOMEvent *event, + GError **error); + + gboolean (* add_event_listener)(WebKitDOMEventTarget *target, + const char *eventName, + GCallback handler, + gboolean bubble, + gpointer userData); + gboolean (* remove_event_listener)(WebKitDOMEventTarget *target, + const char *eventName, + GCallback handler, + gboolean bubble); }; @@ -49,6 +59,17 @@ WEBKIT_API void webkit_dom_event_target_dispatch_event(WebKitDOMEventTarget WebKitDOMEvent *event, GError **error); +WEBKIT_API gboolean webkit_dom_event_target_add_event_listener(WebKitDOMEventTarget *target, + const char *eventName, + GCallback handler, + gboolean bubble, + gpointer userData); + +WEBKIT_API gboolean webkit_dom_event_target_remove_event_listener(WebKitDOMEventTarget *target, + const char *eventName, + GCallback handler, + gboolean bubble); + G_END_DECLS #endif /* WebKitDOMEventTarget_h */ diff --git a/Source/WebCore/bindings/js/JSAudioConstructor.cpp b/Source/WebCore/bindings/js/JSAudioConstructor.cpp index f0040fa..9ac797b 100644 --- a/Source/WebCore/bindings/js/JSAudioConstructor.cpp +++ b/Source/WebCore/bindings/js/JSAudioConstructor.cpp @@ -40,7 +40,7 @@ namespace WebCore { const ClassInfo JSAudioConstructor::s_info = { "AudioConstructor", &DOMConstructorWithDocument::s_info, 0, 0 }; JSAudioConstructor::JSAudioConstructor(ExecState* exec, JSDOMGlobalObject* globalObject) - : DOMConstructorWithDocument(JSAudioConstructor::createStructure(globalObject->objectPrototype()), globalObject) + : DOMConstructorWithDocument(JSAudioConstructor::createStructure(globalObject->globalData(), globalObject->objectPrototype()), globalObject) { ASSERT(inherits(&s_info)); putDirect(exec->globalData(), exec->propertyNames().prototype, JSHTMLAudioElementPrototype::self(exec, globalObject), None); diff --git a/Source/WebCore/bindings/js/JSAudioConstructor.h b/Source/WebCore/bindings/js/JSAudioConstructor.h index c90abbf..be0b800 100644 --- a/Source/WebCore/bindings/js/JSAudioConstructor.h +++ b/Source/WebCore/bindings/js/JSAudioConstructor.h @@ -38,9 +38,9 @@ namespace WebCore { public: JSAudioConstructor(JSC::ExecState*, JSDOMGlobalObject*); - static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) + static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype) { - return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } static const JSC::ClassInfo s_info; diff --git a/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp b/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp index b53d950..d5c9135 100644 --- a/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp +++ b/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp @@ -103,6 +103,7 @@ #include "JSImageConstructor.cpp" #include "JSImageDataCustom.cpp" #include "JSInjectedScriptHostCustom.cpp" +#include "JSInjectedScriptManager.cpp" #include "JSInspectorFrontendHostCustom.cpp" #include "JSInt16ArrayCustom.cpp" #include "JSInt32ArrayCustom.cpp" @@ -143,6 +144,8 @@ #include "JSUint16ArrayCustom.cpp" #include "JSUint32ArrayCustom.cpp" #include "JSUint8ArrayCustom.cpp" +#include "JSWebKitAnimationCustom.cpp" +#include "JSWebKitAnimationListCustom.cpp" #include "JSWebKitCSSKeyframeRuleCustom.cpp" #include "JSWebKitCSSKeyframesRuleCustom.cpp" #include "JSWebKitCSSMatrixCustom.cpp" @@ -156,6 +159,7 @@ #include "JSXSLTProcessorCustom.cpp" #include "JavaScriptCallFrame.cpp" #include "MemoryInfo.cpp" +#include "PageScriptDebugServer.cpp" #include "ScheduledAction.cpp" #include "ScriptCachedFrameData.cpp" #include "ScriptCallStackFactory.cpp" @@ -169,4 +173,5 @@ #include "ScriptState.cpp" #include "SerializedScriptValue.cpp" #include "WorkerScriptController.cpp" +#include "WorkerScriptDebugServer.cpp" diff --git a/Source/WebCore/bindings/js/JSDOMBinding.cpp b/Source/WebCore/bindings/js/JSDOMBinding.cpp index 4d18a4e..8501eb9 100644 --- a/Source/WebCore/bindings/js/JSDOMBinding.cpp +++ b/Source/WebCore/bindings/js/JSDOMBinding.cpp @@ -483,7 +483,7 @@ JSValue jsDateOrNull(ExecState* exec, double value) { if (!isfinite(value)) return jsNull(); - return new (exec) DateInstance(exec, value); + return new (exec) DateInstance(exec, exec->lexicalGlobalObject()->dateStructure(), value); } double valueToDate(ExecState* exec, JSValue value) diff --git a/Source/WebCore/bindings/js/JSDOMBinding.h b/Source/WebCore/bindings/js/JSDOMBinding.h index 4fe3d16..934d9b3 100644 --- a/Source/WebCore/bindings/js/JSDOMBinding.h +++ b/Source/WebCore/bindings/js/JSDOMBinding.h @@ -64,9 +64,9 @@ namespace WebCore { return globalObject()->scriptExecutionContext(); } - static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) + static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype) { - return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: @@ -83,9 +83,9 @@ namespace WebCore { // Base class for all constructor objects in the JSC bindings. class DOMConstructorObject : public DOMObjectWithGlobalPointer { public: - static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) + static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype) { - return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: @@ -143,7 +143,7 @@ namespace WebCore { { if (JSC::Structure* structure = getCachedDOMStructure(globalObject, &WrapperClass::s_info)) return structure; - return cacheDOMStructure(globalObject, WrapperClass::createStructure(WrapperClass::createPrototype(exec, globalObject)), &WrapperClass::s_info); + return cacheDOMStructure(globalObject, WrapperClass::createStructure(exec->globalData(), WrapperClass::createPrototype(exec, globalObject)), &WrapperClass::s_info); } template<class WrapperClass> inline JSC::Structure* deprecatedGetDOMStructure(JSC::ExecState* exec) { diff --git a/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp b/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp index efd0ae0..8183b6e 100644 --- a/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp +++ b/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp @@ -42,8 +42,10 @@ namespace WebCore { const ClassInfo JSDOMGlobalObject::s_info = { "DOMGlobalObject", &JSGlobalObject::s_info, 0, 0 }; -JSDOMGlobalObject::JSDOMGlobalObject(NonNullPassRefPtr<Structure> structure, JSDOMGlobalObject::JSDOMGlobalObjectData* data, JSObject* thisValue) - : JSGlobalObject(structure, data, thisValue) +JSDOMGlobalObject::JSDOMGlobalObject(NonNullPassRefPtr<Structure> structure, PassRefPtr<DOMWrapperWorld> world, JSObject* thisValue) + : JSGlobalObject(structure, thisValue) + , m_currentEvent(0) + , m_world(world) { ASSERT(inherits(&s_info)); } @@ -60,33 +62,28 @@ void JSDOMGlobalObject::markChildren(MarkStack& markStack) for (JSDOMConstructorMap::iterator it2 = constructors().begin(); it2 != end2; ++it2) markStack.append(&it2->second); - if (d()->m_injectedScript) - markStack.append(&d()->m_injectedScript); + if (m_injectedScript) + markStack.append(&m_injectedScript); } -void JSDOMGlobalObject::setCurrentEvent(Event* evt) +void JSDOMGlobalObject::setCurrentEvent(Event* currentEvent) { - d()->evt = evt; + m_currentEvent = currentEvent; } Event* JSDOMGlobalObject::currentEvent() const { - return d()->evt; + return m_currentEvent; } void JSDOMGlobalObject::setInjectedScript(JSObject* injectedScript) { - d()->m_injectedScript.set(globalData(), this, injectedScript); + m_injectedScript.set(globalData(), this, injectedScript); } JSObject* JSDOMGlobalObject::injectedScript() const { - return d()->m_injectedScript.get(); -} - -void JSDOMGlobalObject::destroyJSDOMGlobalObjectData(void* jsDOMGlobalObjectData) -{ - delete static_cast<JSDOMGlobalObjectData*>(jsDOMGlobalObjectData); + return m_injectedScript.get(); } JSDOMGlobalObject* toJSDOMGlobalObject(Document* document, JSC::ExecState* exec) diff --git a/Source/WebCore/bindings/js/JSDOMGlobalObject.h b/Source/WebCore/bindings/js/JSDOMGlobalObject.h index ac07969..1e992c5 100644 --- a/Source/WebCore/bindings/js/JSDOMGlobalObject.h +++ b/Source/WebCore/bindings/js/JSDOMGlobalObject.h @@ -46,11 +46,11 @@ namespace WebCore { protected: struct JSDOMGlobalObjectData; - JSDOMGlobalObject(NonNullPassRefPtr<JSC::Structure>, JSDOMGlobalObjectData*, JSC::JSObject* thisValue); + JSDOMGlobalObject(NonNullPassRefPtr<JSC::Structure>, PassRefPtr<DOMWrapperWorld>, JSC::JSObject* thisValue); public: - JSDOMStructureMap& structures() { return d()->structures; } - JSDOMConstructorMap& constructors() const { return d()->constructors; } + JSDOMStructureMap& structures() { return m_structures; } + JSDOMConstructorMap& constructors() { return m_constructors; } virtual ScriptExecutionContext* scriptExecutionContext() const = 0; @@ -65,47 +65,33 @@ namespace WebCore { virtual void markChildren(JSC::MarkStack&); - DOMWrapperWorld* world() { return d()->m_world.get(); } + DOMWrapperWorld* world() { return m_world.get(); } static const JSC::ClassInfo s_info; - static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) + static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype) { - return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: - struct JSDOMGlobalObjectData : public JSC::JSGlobalObject::JSGlobalObjectData { - JSDOMGlobalObjectData(DOMWrapperWorld* world, Destructor destructor = destroyJSDOMGlobalObjectData) - : JSGlobalObjectData(destructor) - , evt(0) - , m_world(world) - { - } - - JSDOMStructureMap structures; - JSDOMConstructorMap constructors; - - Event* evt; - RefPtr<DOMWrapperWorld> m_world; - JSC::WriteBarrier<JSObject> m_injectedScript; - }; - - private: - static void destroyJSDOMGlobalObjectData(void*); - - JSDOMGlobalObjectData* d() const { return static_cast<JSDOMGlobalObjectData*>(JSC::JSVariableObject::d); } + JSDOMStructureMap m_structures; + JSDOMConstructorMap m_constructors; + + Event* m_currentEvent; + RefPtr<DOMWrapperWorld> m_world; + JSC::WriteBarrier<JSObject> m_injectedScript; }; template<class ConstructorClass> inline JSC::JSObject* getDOMConstructor(JSC::ExecState* exec, const JSDOMGlobalObject* globalObject) { - if (JSC::JSObject* constructor = globalObject->constructors().get(&ConstructorClass::s_info).get()) + if (JSC::JSObject* constructor = const_cast<JSDOMGlobalObject*>(globalObject)->constructors().get(&ConstructorClass::s_info).get()) return constructor; JSC::JSObject* constructor = new (exec) ConstructorClass(exec, const_cast<JSDOMGlobalObject*>(globalObject)); - ASSERT(!globalObject->constructors().contains(&ConstructorClass::s_info)); + ASSERT(!const_cast<JSDOMGlobalObject*>(globalObject)->constructors().contains(&ConstructorClass::s_info)); JSC::WriteBarrier<JSC::JSObject> temp; - globalObject->constructors().add(&ConstructorClass::s_info, temp).first->second.set(exec->globalData(), globalObject, constructor); + const_cast<JSDOMGlobalObject*>(globalObject)->constructors().add(&ConstructorClass::s_info, temp).first->second.set(exec->globalData(), globalObject, constructor); return constructor; } diff --git a/Source/WebCore/bindings/js/JSDOMWindowBase.cpp b/Source/WebCore/bindings/js/JSDOMWindowBase.cpp index df01f77..584f610 100644 --- a/Source/WebCore/bindings/js/JSDOMWindowBase.cpp +++ b/Source/WebCore/bindings/js/JSDOMWindowBase.cpp @@ -45,21 +45,16 @@ namespace WebCore { const ClassInfo JSDOMWindowBase::s_info = { "Window", &JSDOMGlobalObject::s_info, 0, 0 }; -JSDOMWindowBase::JSDOMWindowBaseData::JSDOMWindowBaseData(PassRefPtr<DOMWindow> window, JSDOMWindowShell* shell) - : JSDOMGlobalObjectData(shell->world(), destroyJSDOMWindowBaseData) - , impl(window) - , shell(shell) -{ -} - JSDOMWindowBase::JSDOMWindowBase(NonNullPassRefPtr<Structure> structure, PassRefPtr<DOMWindow> window, JSDOMWindowShell* shell) - : JSDOMGlobalObject(structure, new JSDOMWindowBaseData(window, shell), shell) + : JSDOMGlobalObject(structure, shell->world(), shell) + , m_impl(window) + , m_shell(shell) { ASSERT(inherits(&s_info)); GlobalPropertyInfo staticGlobals[] = { GlobalPropertyInfo(Identifier(globalExec(), "document"), jsNull(), DontDelete | ReadOnly), - GlobalPropertyInfo(Identifier(globalExec(), "window"), d()->shell, DontDelete | ReadOnly) + GlobalPropertyInfo(Identifier(globalExec(), "window"), m_shell, DontDelete | ReadOnly) }; addStaticGlobals(staticGlobals, WTF_ARRAY_LENGTH(staticGlobals)); @@ -67,19 +62,19 @@ JSDOMWindowBase::JSDOMWindowBase(NonNullPassRefPtr<Structure> structure, PassRef void JSDOMWindowBase::updateDocument() { - ASSERT(d()->impl->document()); + ASSERT(m_impl->document()); ExecState* exec = globalExec(); - symbolTablePutWithAttributes(exec->globalData(), Identifier(exec, "document"), toJS(exec, this, d()->impl->document()), DontDelete | ReadOnly); + symbolTablePutWithAttributes(exec->globalData(), Identifier(exec, "document"), toJS(exec, this, m_impl->document()), DontDelete | ReadOnly); } ScriptExecutionContext* JSDOMWindowBase::scriptExecutionContext() const { - return d()->impl->document(); + return m_impl->document(); } String JSDOMWindowBase::crossDomainAccessErrorMessage(const JSGlobalObject* other) const { - return d()->shell->window()->impl()->crossDomainAccessErrorMessage(asJSDOMWindow(other)->impl()); + return m_shell->window()->impl()->crossDomainAccessErrorMessage(asJSDOMWindow(other)->impl()); } void JSDOMWindowBase::printErrorMessage(const String& message) const @@ -170,7 +165,7 @@ JSValue JSDOMWindowBase::toStrictThisObject(ExecState*) const JSDOMWindowShell* JSDOMWindowBase::shell() const { - return d()->shell; + return m_shell; } JSGlobalData* JSDOMWindowBase::commonJSGlobalData() @@ -190,11 +185,6 @@ JSGlobalData* JSDOMWindowBase::commonJSGlobalData() return globalData; } -void JSDOMWindowBase::destroyJSDOMWindowBaseData(void* jsDOMWindowBaseData) -{ - delete static_cast<JSDOMWindowBaseData*>(jsDOMWindowBaseData); -} - // JSDOMGlobalObject* is ignored, accessing a window in any context will // use that DOMWindow's prototype chain. JSValue toJS(ExecState* exec, JSDOMGlobalObject*, DOMWindow* domWindow) diff --git a/Source/WebCore/bindings/js/JSDOMWindowBase.h b/Source/WebCore/bindings/js/JSDOMWindowBase.h index 91b4f42..bfec31c 100644 --- a/Source/WebCore/bindings/js/JSDOMWindowBase.h +++ b/Source/WebCore/bindings/js/JSDOMWindowBase.h @@ -49,7 +49,7 @@ namespace WebCore { public: void updateDocument(); - DOMWindow* impl() const { return d()->impl.get(); } + DOMWindow* impl() const { return m_impl.get(); } virtual ScriptExecutionContext* scriptExecutionContext() const; // Called just before removing this window from the JSDOMWindowShell. @@ -57,9 +57,9 @@ namespace WebCore { static const JSC::ClassInfo s_info; - static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) + static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype) { - return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } virtual JSC::ExecState* globalExec(); @@ -82,19 +82,11 @@ namespace WebCore { static JSC::JSGlobalData* commonJSGlobalData(); private: - struct JSDOMWindowBaseData : public JSDOMGlobalObjectData { - JSDOMWindowBaseData(PassRefPtr<DOMWindow> window, JSDOMWindowShell* shell); - - RefPtr<DOMWindow> impl; - JSDOMWindowShell* shell; - }; + RefPtr<DOMWindow> m_impl; + JSDOMWindowShell* m_shell; bool allowsAccessFromPrivate(const JSC::JSGlobalObject*) const; String crossDomainAccessErrorMessage(const JSC::JSGlobalObject*) const; - - static void destroyJSDOMWindowBaseData(void*); - - JSDOMWindowBaseData* d() const { return static_cast<JSDOMWindowBaseData*>(JSC::JSVariableObject::d); } }; // Returns a JSDOMWindow or jsNull() diff --git a/Source/WebCore/bindings/js/JSDOMWindowCustom.h b/Source/WebCore/bindings/js/JSDOMWindowCustom.h index a0e1b8f..a8d5a91 100644 --- a/Source/WebCore/bindings/js/JSDOMWindowCustom.h +++ b/Source/WebCore/bindings/js/JSDOMWindowCustom.h @@ -67,7 +67,7 @@ inline bool JSDOMWindowBase::allowsAccessFrom(JSC::ExecState* exec, String& mess ALWAYS_INLINE bool JSDOMWindowBase::allowsAccessFromPrivate(const JSGlobalObject* other) const { const JSDOMWindow* originWindow = asJSDOMWindow(other); - const JSDOMWindow* targetWindow = d()->shell->window(); + const JSDOMWindow* targetWindow = m_shell->window(); if (originWindow == targetWindow) return true; diff --git a/Source/WebCore/bindings/js/JSDOMWindowShell.cpp b/Source/WebCore/bindings/js/JSDOMWindowShell.cpp index a4cc777..817e9c0 100644 --- a/Source/WebCore/bindings/js/JSDOMWindowShell.cpp +++ b/Source/WebCore/bindings/js/JSDOMWindowShell.cpp @@ -44,7 +44,7 @@ ASSERT_CLASS_FITS_IN_CELL(JSDOMWindowShell); const ClassInfo JSDOMWindowShell::s_info = { "JSDOMWindowShell", &Base::s_info, 0, 0 }; JSDOMWindowShell::JSDOMWindowShell(PassRefPtr<DOMWindow> window, DOMWrapperWorld* world) - : Base(JSDOMWindowShell::createStructure(jsNull())) + : Base(JSDOMWindowShell::createStructure(*world->globalData(), jsNull())) , m_world(world) { ASSERT(inherits(&s_info)); @@ -60,10 +60,10 @@ void JSDOMWindowShell::setWindow(PassRefPtr<DOMWindow> domWindow) // Explicitly protect the global object's prototype so it isn't collected // when we allocate the global object. (Once the global object is fully // constructed, it can mark its own prototype.) - RefPtr<Structure> prototypeStructure = JSDOMWindowPrototype::createStructure(jsNull()); + RefPtr<Structure> prototypeStructure = JSDOMWindowPrototype::createStructure(*JSDOMWindow::commonJSGlobalData(), jsNull()); Global<JSDOMWindowPrototype> prototype(*JSDOMWindow::commonJSGlobalData(), new JSDOMWindowPrototype(0, prototypeStructure.release())); - RefPtr<Structure> structure = JSDOMWindow::createStructure(prototype.get()); + RefPtr<Structure> structure = JSDOMWindow::createStructure(*JSDOMWindow::commonJSGlobalData(), prototype.get()); JSDOMWindow* jsDOMWindow = new (JSDOMWindow::commonJSGlobalData()) JSDOMWindow(structure.release(), domWindow, this); prototype->putAnonymousValue(*JSDOMWindow::commonJSGlobalData(), 0, jsDOMWindow); setWindow(*JSDOMWindow::commonJSGlobalData(), jsDOMWindow); diff --git a/Source/WebCore/bindings/js/JSDOMWindowShell.h b/Source/WebCore/bindings/js/JSDOMWindowShell.h index 06dd1ff..4307c1c 100644 --- a/Source/WebCore/bindings/js/JSDOMWindowShell.h +++ b/Source/WebCore/bindings/js/JSDOMWindowShell.h @@ -58,9 +58,9 @@ namespace WebCore { void* operator new(size_t); - static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) + static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype) { - return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } DOMWrapperWorld* world() { return m_world.get(); } diff --git a/Source/WebCore/bindings/js/JSDOMWrapper.cpp b/Source/WebCore/bindings/js/JSDOMWrapper.cpp index 794f039..c91230b 100644 --- a/Source/WebCore/bindings/js/JSDOMWrapper.cpp +++ b/Source/WebCore/bindings/js/JSDOMWrapper.cpp @@ -40,10 +40,4 @@ DOMObject::~DOMObject() #endif -bool DOMObject::defineOwnProperty(ExecState* exec, const Identifier&, PropertyDescriptor&, bool) -{ - throwError(exec, createTypeError(exec, "defineProperty is not supported on DOM Objects")); - return false; -} - } // namespace WebCore diff --git a/Source/WebCore/bindings/js/JSDOMWrapper.h b/Source/WebCore/bindings/js/JSDOMWrapper.h index 2d09f01..0f8031c 100644 --- a/Source/WebCore/bindings/js/JSDOMWrapper.h +++ b/Source/WebCore/bindings/js/JSDOMWrapper.h @@ -34,8 +34,6 @@ protected: { } - virtual bool defineOwnProperty(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&, bool); - #ifndef NDEBUG virtual ~DOMObject(); #endif diff --git a/Source/WebCore/bindings/js/JSErrorHandler.cpp b/Source/WebCore/bindings/js/JSErrorHandler.cpp index ae8e363..3d916e6 100644 --- a/Source/WebCore/bindings/js/JSErrorHandler.cpp +++ b/Source/WebCore/bindings/js/JSErrorHandler.cpp @@ -88,7 +88,7 @@ void JSErrorHandler::handleEvent(ScriptExecutionContext* scriptExecutionContext, args.append(jsNumber(errorEvent->lineno())); JSGlobalData& globalData = globalObject->globalData(); - DynamicGlobalObjectScope globalObjectScope(exec, globalData.dynamicGlobalObject ? globalData.dynamicGlobalObject : globalObject); + DynamicGlobalObjectScope globalObjectScope(globalData, globalData.dynamicGlobalObject ? globalData.dynamicGlobalObject : globalObject); JSValue thisValue = globalObject->toThisObject(exec); diff --git a/Source/WebCore/bindings/js/JSEventListener.cpp b/Source/WebCore/bindings/js/JSEventListener.cpp index 90a164b..e444d88 100644 --- a/Source/WebCore/bindings/js/JSEventListener.cpp +++ b/Source/WebCore/bindings/js/JSEventListener.cpp @@ -108,7 +108,7 @@ void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext globalObject->setCurrentEvent(event); JSGlobalData& globalData = globalObject->globalData(); - DynamicGlobalObjectScope globalObjectScope(exec, globalData.dynamicGlobalObject ? globalData.dynamicGlobalObject : globalObject); + DynamicGlobalObjectScope globalObjectScope(globalData, globalData.dynamicGlobalObject ? globalData.dynamicGlobalObject : globalObject); globalData.timeoutChecker.start(); JSValue retval; diff --git a/Source/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp b/Source/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp index 84dd72e..72aec4b 100644 --- a/Source/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp +++ b/Source/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp @@ -76,6 +76,9 @@ JSValue JSHTMLCanvasElement::getContext(ExecState* exec) Identifier premultipliedAlpha(exec, "premultipliedAlpha"); if (jsAttrs->hasProperty(exec, premultipliedAlpha)) webGLAttrs->setPremultipliedAlpha(jsAttrs->get(exec, premultipliedAlpha).toBoolean(exec)); + Identifier preserveDrawingBuffer(exec, "preserveDrawingBuffer"); + if (jsAttrs->hasProperty(exec, preserveDrawingBuffer)) + webGLAttrs->setPreserveDrawingBuffer(jsAttrs->get(exec, preserveDrawingBuffer).toBoolean(exec)); } } #endif diff --git a/Source/WebCore/bindings/js/JSImageConstructor.cpp b/Source/WebCore/bindings/js/JSImageConstructor.cpp index 1ddf136..be75af0 100644 --- a/Source/WebCore/bindings/js/JSImageConstructor.cpp +++ b/Source/WebCore/bindings/js/JSImageConstructor.cpp @@ -35,7 +35,7 @@ ASSERT_CLASS_FITS_IN_CELL(JSImageConstructor); const ClassInfo JSImageConstructor::s_info = { "ImageConstructor", &DOMConstructorWithDocument::s_info, 0, 0 }; JSImageConstructor::JSImageConstructor(ExecState* exec, JSDOMGlobalObject* globalObject) - : DOMConstructorWithDocument(JSImageConstructor::createStructure(globalObject->objectPrototype()), globalObject) + : DOMConstructorWithDocument(JSImageConstructor::createStructure(globalObject->globalData(), globalObject->objectPrototype()), globalObject) { ASSERT(inherits(&s_info)); putDirect(exec->globalData(), exec->propertyNames().prototype, JSHTMLImageElementPrototype::self(exec, globalObject), None); diff --git a/Source/WebCore/bindings/js/JSImageConstructor.h b/Source/WebCore/bindings/js/JSImageConstructor.h index 73293c7..654e223 100644 --- a/Source/WebCore/bindings/js/JSImageConstructor.h +++ b/Source/WebCore/bindings/js/JSImageConstructor.h @@ -29,9 +29,9 @@ namespace WebCore { public: JSImageConstructor(JSC::ExecState*, JSDOMGlobalObject*); - static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) + static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype) { - return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } static const JSC::ClassInfo s_info; diff --git a/Source/WebCore/bindings/js/JSImageDataCustom.cpp b/Source/WebCore/bindings/js/JSImageDataCustom.cpp index b5592d8..a92ed47 100644 --- a/Source/WebCore/bindings/js/JSImageDataCustom.cpp +++ b/Source/WebCore/bindings/js/JSImageDataCustom.cpp @@ -48,7 +48,7 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, ImageData* imageD wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, ImageData, imageData); Identifier dataName(exec, "data"); static const ClassInfo cpaClassInfo = { "CanvasPixelArray", &JSByteArray::Base::s_info, 0, 0 }; - DEFINE_STATIC_LOCAL(RefPtr<Structure>, cpaStructure, (JSByteArray::createStructure(jsNull(), &cpaClassInfo))); + DEFINE_STATIC_LOCAL(RefPtr<Structure>, cpaStructure, (JSByteArray::createStructure(exec->globalData(), jsNull(), &cpaClassInfo))); wrapper->putDirect(exec->globalData(), dataName, new (exec) JSByteArray(exec, cpaStructure, imageData->data()->data()), DontDelete | ReadOnly); exec->heap()->reportExtraMemoryCost(imageData->data()->length()); diff --git a/Source/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp b/Source/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp index bc1d877..d56251f 100644 --- a/Source/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp +++ b/Source/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp @@ -1,7 +1,7 @@ /* * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com> - * Copyright (C) 2010 Google Inc. All rights reserved. + * Copyright (C) 2010-2011 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 @@ -35,37 +35,21 @@ #if ENABLE(INSPECTOR) -#include "Console.h" -#include "JSMainThreadExecState.h" #if ENABLE(DATABASE) #include "Database.h" #include "JSDatabase.h" #endif #include "ExceptionCode.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "InjectedScript.h" #include "InjectedScriptHost.h" -#include "InspectorAgent.h" +#include "InspectorDebuggerAgent.h" #include "InspectorValues.h" -#include "JSDOMWindow.h" -#include "JSDOMWindowCustom.h" #include "JSNode.h" -#include "JSRange.h" -#include "Node.h" -#include "Page.h" #include "ScriptValue.h" #if ENABLE(DOM_STORAGE) #include "Storage.h" #include "JSStorage.h" #endif -#include "TextIterator.h" -#include "VisiblePosition.h" -#include <parser/SourceCode.h> -#include <runtime/JSArray.h> #include <runtime/JSLock.h> -#include <wtf/RefPtr.h> -#include <wtf/Vector.h> #if ENABLE(JAVASCRIPT_DEBUGGER) #include "JavaScriptCallFrame.h" @@ -89,41 +73,10 @@ ScriptValue InjectedScriptHost::nodeAsScriptValue(ScriptState* state, Node* node return ScriptValue(state->globalData(), toJS(state, node)); } -ScriptObject InjectedScriptHost::createInjectedScript(const String& source, ScriptState* scriptState, long id) -{ - SourceCode sourceCode = makeSource(stringToUString(source)); - JSLock lock(SilenceAssertionsOnly); - JSDOMGlobalObject* globalObject = static_cast<JSDOMGlobalObject*>(scriptState->lexicalGlobalObject()); - JSValue globalThisValue = scriptState->globalThisValue(); - Completion comp = JSMainThreadExecState::evaluate(scriptState, globalObject->globalScopeChain(), sourceCode, globalThisValue); - if (comp.complType() != JSC::Normal && comp.complType() != JSC::ReturnValue) - return ScriptObject(); - JSValue functionValue = comp.value(); - CallData callData; - CallType callType = getCallData(functionValue, callData); - if (callType == CallTypeNone) - return ScriptObject(); - - MarkedArgumentBuffer args; - args.append(toJS(scriptState, globalObject, this)); - args.append(globalThisValue); - args.append(jsNumber(id)); - JSValue result = JSC::call(scriptState, functionValue, callType, callData, globalThisValue, args); - if (result.isObject()) - return ScriptObject(scriptState, result.getObject()); - return ScriptObject(); -} - -void InjectedScriptHost::discardInjectedScript(ScriptState* scriptState) -{ - JSDOMGlobalObject* globalObject = static_cast<JSDOMGlobalObject*>(scriptState->lexicalGlobalObject()); - globalObject->setInjectedScript(0); -} - JSValue JSInjectedScriptHost::currentCallFrame(ExecState* exec) { #if ENABLE(JAVASCRIPT_DEBUGGER) - JavaScriptCallFrame* callFrame = ScriptDebugServer::shared().currentCallFrame(); + JavaScriptCallFrame* callFrame = impl()->debuggerAgent()->scriptDebugServer().currentCallFrame(); if (!callFrame || !callFrame->isValid()) return jsUndefined(); @@ -160,9 +113,9 @@ JSValue JSInjectedScriptHost::internalConstructorName(ExecState* exec) JSValue JSInjectedScriptHost::inspect(ExecState* exec) { if (exec->argumentCount() >= 2) { - ScriptValue objectId(exec->globalData(), exec->argument(0)); + ScriptValue object(exec->globalData(), exec->argument(0)); ScriptValue hints(exec->globalData(), exec->argument(1)); - impl()->inspectImpl(objectId.toInspectorValue(exec), hints.toInspectorValue(exec)); + impl()->inspectImpl(object.toInspectorValue(exec), hints.toInspectorValue(exec)); } return jsUndefined(); } @@ -191,33 +144,6 @@ JSValue JSInjectedScriptHost::storageId(ExecState* exec) return jsUndefined(); } -InjectedScript InjectedScriptHost::injectedScriptFor(ScriptState* scriptState) -{ - JSLock lock(SilenceAssertionsOnly); - JSDOMGlobalObject* globalObject = static_cast<JSDOMGlobalObject*>(scriptState->lexicalGlobalObject()); - JSObject* injectedScript = globalObject->injectedScript(); - if (injectedScript) - return InjectedScript(ScriptObject(scriptState, injectedScript)); - - if (!canAccessInspectedWindow(scriptState)) - return InjectedScript(); - - pair<long, ScriptObject> injectedScriptObject = injectScript(injectedScriptSource(), scriptState); - globalObject->setInjectedScript(injectedScriptObject.second.jsObject()); - InjectedScript result(injectedScriptObject.second); - m_idToInjectedScript.set(injectedScriptObject.first, result); - return result; -} - -bool InjectedScriptHost::canAccessInspectedWindow(ScriptState* scriptState) -{ - JSLock lock(SilenceAssertionsOnly); - JSDOMWindow* inspectedWindow = toJSDOMWindow(scriptState->lexicalGlobalObject()); - if (!inspectedWindow) - return false; - return inspectedWindow->allowsAccessFromNoErrorMessage(scriptState); -} - } // namespace WebCore #endif // ENABLE(INSPECTOR) diff --git a/Source/WebCore/bindings/js/JSInjectedScriptManager.cpp b/Source/WebCore/bindings/js/JSInjectedScriptManager.cpp new file mode 100644 index 0000000..1843cd2 --- /dev/null +++ b/Source/WebCore/bindings/js/JSInjectedScriptManager.cpp @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com> + * Copyright (C) 2010-2011 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 "InjectedScriptManager.h" + +#if ENABLE(INSPECTOR) + +#include "ExceptionCode.h" +#include "InjectedScript.h" +#include "JSDOMWindow.h" +#include "JSDOMWindowCustom.h" +#include "JSInjectedScriptHost.h" +#include "JSMainThreadExecState.h" +#include <parser/SourceCode.h> +#include <runtime/JSLock.h> + +using namespace JSC; + +namespace WebCore { + +ScriptObject InjectedScriptManager::createInjectedScript(const String& source, ScriptState* scriptState, long id) +{ + SourceCode sourceCode = makeSource(stringToUString(source)); + JSLock lock(SilenceAssertionsOnly); + JSDOMGlobalObject* globalObject = static_cast<JSDOMGlobalObject*>(scriptState->lexicalGlobalObject()); + JSValue globalThisValue = scriptState->globalThisValue(); + Completion comp = JSMainThreadExecState::evaluate(scriptState, globalObject->globalScopeChain(), sourceCode, globalThisValue); + if (comp.complType() != JSC::Normal && comp.complType() != JSC::ReturnValue) + return ScriptObject(); + JSValue functionValue = comp.value(); + CallData callData; + CallType callType = getCallData(functionValue, callData); + if (callType == CallTypeNone) + return ScriptObject(); + + MarkedArgumentBuffer args; + args.append(toJS(scriptState, globalObject, m_injectedScriptHost.get())); + args.append(globalThisValue); + args.append(jsNumber(id)); + JSValue result = JSC::call(scriptState, functionValue, callType, callData, globalThisValue, args); + if (result.isObject()) + return ScriptObject(scriptState, result.getObject()); + return ScriptObject(); +} + +void InjectedScriptManager::discardInjectedScript(ScriptState* scriptState) +{ + JSDOMGlobalObject* globalObject = static_cast<JSDOMGlobalObject*>(scriptState->lexicalGlobalObject()); + globalObject->setInjectedScript(0); +} + +InjectedScript InjectedScriptManager::injectedScriptFor(ScriptState* scriptState) +{ + JSLock lock(SilenceAssertionsOnly); + JSDOMGlobalObject* globalObject = static_cast<JSDOMGlobalObject*>(scriptState->lexicalGlobalObject()); + JSObject* injectedScript = globalObject->injectedScript(); + if (injectedScript) + return InjectedScript(ScriptObject(scriptState, injectedScript)); + + if (!canAccessInspectedWindow(scriptState)) + return InjectedScript(); + + pair<long, ScriptObject> injectedScriptObject = injectScript(injectedScriptSource(), scriptState); + globalObject->setInjectedScript(injectedScriptObject.second.jsObject()); + InjectedScript result(injectedScriptObject.second); + m_idToInjectedScript.set(injectedScriptObject.first, result); + return result; +} + +bool InjectedScriptManager::canAccessInspectedWindow(ScriptState* scriptState) +{ + JSLock lock(SilenceAssertionsOnly); + JSDOMWindow* inspectedWindow = toJSDOMWindow(scriptState->lexicalGlobalObject()); + if (!inspectedWindow) + return false; + return inspectedWindow->allowsAccessFromNoErrorMessage(scriptState); +} + +} // namespace WebCore + +#endif // ENABLE(INSPECTOR) diff --git a/Source/WebCore/bindings/js/JSJavaScriptCallFrameCustom.cpp b/Source/WebCore/bindings/js/JSJavaScriptCallFrameCustom.cpp index e493508..e477a50 100644 --- a/Source/WebCore/bindings/js/JSJavaScriptCallFrameCustom.cpp +++ b/Source/WebCore/bindings/js/JSJavaScriptCallFrameCustom.cpp @@ -49,7 +49,7 @@ JSValue JSJavaScriptCallFrame::evaluate(ExecState* exec) JSValue JSJavaScriptCallFrame::thisObject(ExecState*) const { - return impl()->thisObject() ? impl()->thisObject() : jsNull(); + return impl()->thisObject() ? JSValue(impl()->thisObject()) : jsNull(); } JSValue JSJavaScriptCallFrame::type(ExecState* exec) const diff --git a/Source/WebCore/bindings/js/JSLazyEventListener.cpp b/Source/WebCore/bindings/js/JSLazyEventListener.cpp index 98db97a..5b17727 100644 --- a/Source/WebCore/bindings/js/JSLazyEventListener.cpp +++ b/Source/WebCore/bindings/js/JSLazyEventListener.cpp @@ -20,6 +20,7 @@ #include "config.h" #include "JSLazyEventListener.h" +#include "ContentSecurityPolicy.h" #include "Frame.h" #include "JSNode.h" #include <runtime/FunctionConstructor.h> @@ -74,36 +75,29 @@ JSObject* JSLazyEventListener::initializeJSFunction(ScriptExecutionContext* exec if (!executionContext) return 0; - Frame* frame = static_cast<Document*>(executionContext)->frame(); - if (!frame) + Document* document = static_cast<Document*>(executionContext); + + if (!document->frame()) + return 0; + + if (!document->contentSecurityPolicy()->allowInlineEventHandlers()) return 0; - ScriptController* scriptController = frame->script(); - if (!scriptController->canExecuteScripts(AboutToExecuteScript)) + ScriptController* script = document->frame()->script(); + if (!script->canExecuteScripts(AboutToExecuteScript) || script->isPaused()) return 0; JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(executionContext, isolatedWorld()); if (!globalObject) return 0; - if (executionContext->isDocument()) { - JSDOMWindow* window = static_cast<JSDOMWindow*>(globalObject); - Frame* frame = window->impl()->frame(); - if (!frame) - return 0; - // FIXME: Is this check needed for non-Document contexts? - ScriptController* script = frame->script(); - if (!script->canExecuteScripts(AboutToExecuteScript) || script->isPaused()) - return 0; - } - ExecState* exec = globalObject->globalExec(); MarkedArgumentBuffer args; args.append(jsNontrivialString(exec, stringToUString(m_eventParameterName))); args.append(jsString(exec, m_code)); - JSObject* jsFunction = constructFunction(exec, args, Identifier(exec, stringToUString(m_functionName)), stringToUString(m_sourceURL), m_lineNumber); // FIXME: is globalExec ok? + JSObject* jsFunction = constructFunction(exec, exec->lexicalGlobalObject(), args, Identifier(exec, stringToUString(m_functionName)), stringToUString(m_sourceURL), m_lineNumber); // FIXME: is globalExec ok? if (exec->hadException()) { exec->clearException(); return 0; diff --git a/Source/WebCore/bindings/js/JSMainThreadExecState.h b/Source/WebCore/bindings/js/JSMainThreadExecState.h index fb01000..436de5e 100644 --- a/Source/WebCore/bindings/js/JSMainThreadExecState.h +++ b/Source/WebCore/bindings/js/JSMainThreadExecState.h @@ -26,7 +26,7 @@ #ifndef JSMainThreadExecState_h #define JSMainThreadExecState_h -#include <JSDOMBinding.h> +#include "JSDOMBinding.h" #ifndef NDEBUG #include <wtf/MainThread.h> #endif diff --git a/Source/WebCore/bindings/js/JSOptionConstructor.cpp b/Source/WebCore/bindings/js/JSOptionConstructor.cpp index a3c9aab..59e0b6a 100644 --- a/Source/WebCore/bindings/js/JSOptionConstructor.cpp +++ b/Source/WebCore/bindings/js/JSOptionConstructor.cpp @@ -36,7 +36,7 @@ ASSERT_CLASS_FITS_IN_CELL(JSOptionConstructor); const ClassInfo JSOptionConstructor::s_info = { "OptionConstructor", &DOMConstructorWithDocument::s_info, 0, 0 }; JSOptionConstructor::JSOptionConstructor(ExecState* exec, JSDOMGlobalObject* globalObject) - : DOMConstructorWithDocument(JSOptionConstructor::createStructure(globalObject->objectPrototype()), globalObject) + : DOMConstructorWithDocument(JSOptionConstructor::createStructure(globalObject->globalData(), globalObject->objectPrototype()), globalObject) { ASSERT(inherits(&s_info)); putDirect(exec->globalData(), exec->propertyNames().prototype, JSHTMLOptionElementPrototype::self(exec, globalObject), None); diff --git a/Source/WebCore/bindings/js/JSOptionConstructor.h b/Source/WebCore/bindings/js/JSOptionConstructor.h index 03633c7..8a18007 100644 --- a/Source/WebCore/bindings/js/JSOptionConstructor.h +++ b/Source/WebCore/bindings/js/JSOptionConstructor.h @@ -30,9 +30,9 @@ namespace WebCore { public: JSOptionConstructor(JSC::ExecState*, JSDOMGlobalObject*); - static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) + static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype) { - return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } static const JSC::ClassInfo s_info; diff --git a/Source/WebCore/bindings/js/JSWebKitAnimationCustom.cpp b/Source/WebCore/bindings/js/JSWebKitAnimationCustom.cpp new file mode 100644 index 0000000..8425c4c --- /dev/null +++ b/Source/WebCore/bindings/js/JSWebKitAnimationCustom.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2011 Apple Inc. All right reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JSWebKitAnimation.h" + +#include "WebKitAnimation.h" + +using namespace JSC; + +namespace WebCore { + +JSValue JSWebKitAnimation::iterationCount(ExecState*) const +{ + WebKitAnimation* imp = impl(); + int count = imp->iterationCount(); + if (count == Animation::IterationCountInfinite) + return jsNumber(std::numeric_limits<float>::infinity()); + return jsNumber(count); +} + +} diff --git a/Source/WebCore/bindings/js/JSWebKitAnimationListCustom.cpp b/Source/WebCore/bindings/js/JSWebKitAnimationListCustom.cpp new file mode 100644 index 0000000..eaf77cf --- /dev/null +++ b/Source/WebCore/bindings/js/JSWebKitAnimationListCustom.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2011 Apple Inc. All right reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JSWebKitAnimationList.h" + +#include "WebKitAnimationList.h" + +using namespace JSC; + +namespace WebCore { + +void JSWebKitAnimationList::markChildren(MarkStack& markStack) +{ + Base::markChildren(markStack); + + WebKitAnimationList* list = impl(); + JSGlobalData& globalData = *Heap::heap(this)->globalData(); + + unsigned length = list->length(); + for (unsigned i = 0; i < length; ++i) + markDOMObjectWrapper(markStack, globalData, list->item(i)); +} + +} diff --git a/Source/WebCore/bindings/js/JSWorkerContextBase.cpp b/Source/WebCore/bindings/js/JSWorkerContextBase.cpp index 88fa43f..c6f86b5 100644 --- a/Source/WebCore/bindings/js/JSWorkerContextBase.cpp +++ b/Source/WebCore/bindings/js/JSWorkerContextBase.cpp @@ -45,7 +45,7 @@ ASSERT_CLASS_FITS_IN_CELL(JSWorkerContextBase); const ClassInfo JSWorkerContextBase::s_info = { "WorkerContext", &JSDOMGlobalObject::s_info, 0, 0 }; JSWorkerContextBase::JSWorkerContextBase(NonNullPassRefPtr<JSC::Structure> structure, PassRefPtr<WorkerContext> impl) - : JSDOMGlobalObject(structure, new JSDOMGlobalObjectData(normalWorld(*impl->script()->globalData())), this) + : JSDOMGlobalObject(structure, normalWorld(*impl->script()->globalData()), this) , m_impl(impl) { ASSERT(inherits(&s_info)); diff --git a/Source/WebCore/bindings/js/JSWorkerContextBase.h b/Source/WebCore/bindings/js/JSWorkerContextBase.h index 99948b7..b9c234a 100644 --- a/Source/WebCore/bindings/js/JSWorkerContextBase.h +++ b/Source/WebCore/bindings/js/JSWorkerContextBase.h @@ -49,9 +49,9 @@ namespace WebCore { WorkerContext* impl() const { return m_impl.get(); } virtual ScriptExecutionContext* scriptExecutionContext() const; - static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) + static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype) { - return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } private: diff --git a/Source/WebCore/bindings/js/PageScriptDebugServer.cpp b/Source/WebCore/bindings/js/PageScriptDebugServer.cpp new file mode 100755 index 0000000..3d9cb9d --- /dev/null +++ b/Source/WebCore/bindings/js/PageScriptDebugServer.cpp @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2011 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 "PageScriptDebugServer.h" + +#if ENABLE(JAVASCRIPT_DEBUGGER) + +#include "Frame.h" +#include "FrameView.h" +#include "JSDOMWindowCustom.h" +#include "Page.h" +#include "PageGroup.h" +#include "PluginView.h" +#include "ScriptDebugListener.h" +#include "Widget.h" +#include <runtime/JSLock.h> +#include <wtf/MainThread.h> +#include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> +#include <wtf/StdLibExtras.h> + +using namespace JSC; + +namespace WebCore { + +static Page* toPage(JSGlobalObject* globalObject) +{ + ASSERT_ARG(globalObject, globalObject); + + JSDOMWindow* window = asJSDOMWindow(globalObject); + Frame* frame = window->impl()->frame(); + return frame ? frame->page() : 0; +} + +PageScriptDebugServer& PageScriptDebugServer::shared() +{ + DEFINE_STATIC_LOCAL(PageScriptDebugServer, server, ()); + return server; +} + +PageScriptDebugServer::PageScriptDebugServer() + : ScriptDebugServer() +{ +} + +PageScriptDebugServer::~PageScriptDebugServer() +{ + deleteAllValues(m_pageListenersMap); +} + +void PageScriptDebugServer::addListener(ScriptDebugListener* listener, Page* page) +{ + ASSERT_ARG(listener, listener); + ASSERT_ARG(page, page); + + pair<PageListenersMap::iterator, bool> result = m_pageListenersMap.add(page, 0); + if (result.second) + result.first->second = new ListenerSet; + + ListenerSet* listeners = result.first->second; + listeners->add(listener); + + recompileAllJSFunctionsSoon(); + page->setDebugger(this); +} + +void PageScriptDebugServer::removeListener(ScriptDebugListener* listener, Page* page) +{ + ASSERT_ARG(listener, listener); + ASSERT_ARG(page, page); + + PageListenersMap::iterator it = m_pageListenersMap.find(page); + if (it == m_pageListenersMap.end()) + return; + + ListenerSet* listeners = it->second; + listeners->remove(listener); + if (listeners->isEmpty()) { + m_pageListenersMap.remove(it); + delete listeners; + didRemoveLastListener(page); + } +} + +void PageScriptDebugServer::recompileAllJSFunctions(Timer<ScriptDebugServer>*) +{ + JSLock lock(SilenceAssertionsOnly); + // If JavaScript stack is not empty postpone recompilation. + if (JSDOMWindow::commonJSGlobalData()->dynamicGlobalObject) + recompileAllJSFunctionsSoon(); + else + Debugger::recompileAllJSFunctions(JSDOMWindow::commonJSGlobalData()); +} + +ScriptDebugServer::ListenerSet* PageScriptDebugServer::getListenersForGlobalObject(JSGlobalObject* globalObject) +{ + Page* page = toPage(globalObject); + if (!page) + return 0; + return m_pageListenersMap.get(page); +} + +void PageScriptDebugServer::didPause(JSC::JSGlobalObject* globalObject) +{ + Page* page = toPage(globalObject); + m_pausedPage = page; + setJavaScriptPaused(page->group(), true); +} + +void PageScriptDebugServer::didContinue(JSC::JSGlobalObject* globalObject) +{ + Page* page = toPage(globalObject); + m_pausedPage = 0; + setJavaScriptPaused(page->group(), false); +} + +void PageScriptDebugServer::didRemoveLastListener(Page* page) +{ + if (m_pausedPage == page) + m_doneProcessingDebuggerEvents = true; + + recompileAllJSFunctionsSoon(); + page->setDebugger(0); +} + +void PageScriptDebugServer::setJavaScriptPaused(const PageGroup& pageGroup, bool paused) +{ + setMainThreadCallbacksPaused(paused); + + const HashSet<Page*>& pages = pageGroup.pages(); + + HashSet<Page*>::const_iterator end = pages.end(); + for (HashSet<Page*>::const_iterator it = pages.begin(); it != end; ++it) + setJavaScriptPaused(*it, paused); +} + +void PageScriptDebugServer::setJavaScriptPaused(Page* page, bool paused) +{ + ASSERT_ARG(page, page); + + page->setDefersLoading(paused); + + for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext()) + setJavaScriptPaused(frame, paused); +} + +void PageScriptDebugServer::setJavaScriptPaused(Frame* frame, bool paused) +{ + ASSERT_ARG(frame, frame); + + if (!frame->script()->canExecuteScripts(NotAboutToExecuteScript)) + return; + + frame->script()->setPaused(paused); + + Document* document = frame->document(); + if (paused) { + document->suspendScriptedAnimationControllerCallbacks(); + document->suspendActiveDOMObjects(ActiveDOMObject::JavaScriptDebuggerPaused); + } else { + document->resumeActiveDOMObjects(); + document->resumeScriptedAnimationControllerCallbacks(); + } + + setJavaScriptPaused(frame->view(), paused); +} + +void PageScriptDebugServer::setJavaScriptPaused(FrameView* view, bool paused) +{ + if (!view) + return; + + const HashSet<RefPtr<Widget> >* children = view->children(); + ASSERT(children); + + HashSet<RefPtr<Widget> >::const_iterator end = children->end(); + for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != end; ++it) { + Widget* widget = (*it).get(); + if (!widget->isPluginView()) + continue; + static_cast<PluginView*>(widget)->setJavaScriptPaused(paused); + } +} + +} // namespace WebCore + +#endif // ENABLE(JAVASCRIPT_DEBUGGER) diff --git a/Source/WebCore/bindings/js/PageScriptDebugServer.h b/Source/WebCore/bindings/js/PageScriptDebugServer.h new file mode 100755 index 0000000..5563e26 --- /dev/null +++ b/Source/WebCore/bindings/js/PageScriptDebugServer.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2011 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 PageScriptDebugServer_h +#define PageScriptDebugServer_h + +#if ENABLE(JAVASCRIPT_DEBUGGER) + +#include "ScriptDebugServer.h" +#include <wtf/Forward.h> + +namespace WebCore { + +class Frame; +class FrameView; +class Page; +class PageGroup; + +class PageScriptDebugServer : public ScriptDebugServer { + WTF_MAKE_NONCOPYABLE(PageScriptDebugServer); +public: + static PageScriptDebugServer& shared(); + + void addListener(ScriptDebugListener*, Page*); + void removeListener(ScriptDebugListener*, Page*); + + virtual void recompileAllJSFunctions(Timer<ScriptDebugServer>*); + +private: + typedef HashMap<Page*, ListenerSet*> PageListenersMap; + + PageScriptDebugServer(); + virtual ~PageScriptDebugServer(); + + virtual ListenerSet* getListenersForGlobalObject(JSC::JSGlobalObject*); + virtual void didPause(JSC::JSGlobalObject*); + virtual void didContinue(JSC::JSGlobalObject*); + + void didRemoveLastListener(Page*); + + void setJavaScriptPaused(const PageGroup&, bool paused); + void setJavaScriptPaused(Page*, bool paused); + void setJavaScriptPaused(Frame*, bool paused); + void setJavaScriptPaused(FrameView*, bool paused); + + PageListenersMap m_pageListenersMap; + Page* m_pausedPage; +}; + +} // namespace WebCore + +#endif // ENABLE(JAVASCRIPT_DEBUGGER) + +#endif // PageScriptDebugServer_h diff --git a/Source/WebCore/bindings/js/ScheduledAction.h b/Source/WebCore/bindings/js/ScheduledAction.h index c4b3edf..3adc185 100644 --- a/Source/WebCore/bindings/js/ScheduledAction.h +++ b/Source/WebCore/bindings/js/ScheduledAction.h @@ -20,8 +20,8 @@ #ifndef ScheduledAction_h #define ScheduledAction_h +#include "JSDOMBinding.h" #include "PlatformString.h" -#include <JSDOMBinding.h> #include <collector/handles/Global.h> #include <runtime/JSCell.h> #include <wtf/PassOwnPtr.h> diff --git a/Source/WebCore/bindings/js/ScriptDebugServer.cpp b/Source/WebCore/bindings/js/ScriptDebugServer.cpp index 32a3b2d..05c0f2c 100644 --- a/Source/WebCore/bindings/js/ScriptDebugServer.cpp +++ b/Source/WebCore/bindings/js/ScriptDebugServer.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. - * Copyright (C) 2010 Google Inc. All rights reserved. + * Copyright (C) 2010-2011 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,45 +32,27 @@ #if ENABLE(JAVASCRIPT_DEBUGGER) -#include "DOMWindow.h" #include "EventLoop.h" #include "Frame.h" -#include "FrameTree.h" -#include "FrameView.h" -#include "JSDOMWindowCustom.h" #include "JavaScriptCallFrame.h" -#include "Page.h" -#include "PageGroup.h" -#include "PluginView.h" #include "ScriptBreakpoint.h" #include "ScriptController.h" #include "ScriptDebugListener.h" -#include "ScrollView.h" -#include "Widget.h" #include <debugger/DebuggerCallFrame.h> #include <parser/SourceProvider.h> #include <runtime/JSLock.h> #include <wtf/text/StringConcatenate.h> #include <wtf/MainThread.h> -#include <wtf/StdLibExtras.h> -#include <wtf/UnusedParam.h> using namespace JSC; namespace WebCore { -ScriptDebugServer& ScriptDebugServer::shared() -{ - DEFINE_STATIC_LOCAL(ScriptDebugServer, server, ()); - return server; -} - ScriptDebugServer::ScriptDebugServer() : m_callingListeners(false) , m_pauseOnExceptionsState(DontPauseOnExceptions) , m_pauseOnNextStatement(false) , m_paused(false) - , m_pausedPage(0) , m_doneProcessingDebuggerEvents(true) , m_breakpointsActivated(true) , m_pauseOnCallFrame(0) @@ -83,47 +65,6 @@ ScriptDebugServer::~ScriptDebugServer() deleteAllValues(m_pageListenersMap); } -void ScriptDebugServer::addListener(ScriptDebugListener* listener, Page* page) -{ - ASSERT_ARG(listener, listener); - ASSERT_ARG(page, page); - - pair<PageListenersMap::iterator, bool> result = m_pageListenersMap.add(page, 0); - if (result.second) - result.first->second = new ListenerSet; - - ListenerSet* listeners = result.first->second; - listeners->add(listener); - - didAddListener(page); -} - -void ScriptDebugServer::removeListener(ScriptDebugListener* listener, Page* page) -{ - ASSERT_ARG(listener, listener); - ASSERT_ARG(page, page); - - PageListenersMap::iterator it = m_pageListenersMap.find(page); - if (it == m_pageListenersMap.end()) - return; - - ListenerSet* listeners = it->second; - listeners->remove(listener); - if (listeners->isEmpty()) { - m_pageListenersMap.remove(it); - delete listeners; - } - - didRemoveListener(page); -} - -bool ScriptDebugServer::hasListenersInterestedInPage(Page* page) -{ - ASSERT_ARG(page, page); - - return m_pageListenersMap.contains(page); -} - String ScriptDebugServer::setBreakpoint(const String& sourceID, const ScriptBreakpoint& scriptBreakpoint, int* actualLineNumber, int* actualColumnNumber) { intptr_t sourceIDValue = sourceID.toIntPtr(); @@ -299,15 +240,6 @@ void ScriptDebugServer::dispatchFailedToParseSource(const ListenerSet& listeners copy[i]->failedToParseSource(url, data, firstLine, errorLine, errorMessage); } -static Page* toPage(JSGlobalObject* globalObject) -{ - ASSERT_ARG(globalObject, globalObject); - - JSDOMWindow* window = asJSDOMWindow(globalObject); - Frame* frame = window->impl()->frame(); - return frame ? frame->page() : 0; -} - static ScriptWorldType currentWorldType(ExecState* exec) { if (currentWorld(exec) == mainThreadNormalWorld()) @@ -333,22 +265,19 @@ void ScriptDebugServer::sourceParsed(ExecState* exec, SourceProvider* sourceProv if (m_callingListeners) return; - Page* page = toPage(exec->lexicalGlobalObject()); - if (!page) + ListenerSet* listeners = getListenersForGlobalObject(exec->lexicalGlobalObject()); + if (!listeners) return; - - ScriptWorldType worldType = currentWorldType(exec); + ASSERT(!listeners->isEmpty()); m_callingListeners = true; bool isError = errorLine != -1; - - if (ListenerSet* pageListeners = m_pageListenersMap.get(page)) { - ASSERT(!pageListeners->isEmpty()); - if (isError) - dispatchFailedToParseSource(*pageListeners, sourceProvider, errorLine, ustringToString(errorMessage)); - else - dispatchDidParseSource(*pageListeners, sourceProvider, worldType); + if (isError) + dispatchFailedToParseSource(*listeners, sourceProvider, errorLine, ustringToString(errorMessage)); + else { + ScriptWorldType worldType = currentWorldType(exec); + dispatchDidParseSource(*listeners, sourceProvider, worldType); } m_callingListeners = false; @@ -362,85 +291,26 @@ void ScriptDebugServer::dispatchFunctionToListeners(const ListenerSet& listeners (this->*callback)(copy[i]); } -void ScriptDebugServer::dispatchFunctionToListeners(JavaScriptExecutionCallback callback, Page* page) +void ScriptDebugServer::dispatchFunctionToListeners(JavaScriptExecutionCallback callback, JSGlobalObject* globalObject) { if (m_callingListeners) return; m_callingListeners = true; - if (ListenerSet* pageListeners = m_pageListenersMap.get(page)) { - ASSERT(!pageListeners->isEmpty()); - dispatchFunctionToListeners(*pageListeners, callback); + if (ListenerSet* listeners = getListenersForGlobalObject(globalObject)) { + ASSERT(!listeners->isEmpty()); + dispatchFunctionToListeners(*listeners, callback); } m_callingListeners = false; } -void ScriptDebugServer::setJavaScriptPaused(const PageGroup& pageGroup, bool paused) -{ - setMainThreadCallbacksPaused(paused); - - const HashSet<Page*>& pages = pageGroup.pages(); - - HashSet<Page*>::const_iterator end = pages.end(); - for (HashSet<Page*>::const_iterator it = pages.begin(); it != end; ++it) - setJavaScriptPaused(*it, paused); -} - -void ScriptDebugServer::setJavaScriptPaused(Page* page, bool paused) -{ - ASSERT_ARG(page, page); - - page->setDefersLoading(paused); - - for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext()) - setJavaScriptPaused(frame, paused); -} - -void ScriptDebugServer::setJavaScriptPaused(Frame* frame, bool paused) -{ - ASSERT_ARG(frame, frame); - - if (!frame->script()->canExecuteScripts(NotAboutToExecuteScript)) - return; - - frame->script()->setPaused(paused); - - Document* document = frame->document(); - if (paused) { - document->suspendScriptedAnimationControllerCallbacks(); - document->suspendActiveDOMObjects(ActiveDOMObject::JavaScriptDebuggerPaused); - } else { - document->resumeActiveDOMObjects(); - document->resumeScriptedAnimationControllerCallbacks(); - } - - setJavaScriptPaused(frame->view(), paused); -} - -void ScriptDebugServer::setJavaScriptPaused(FrameView* view, bool paused) -{ - if (!view) - return; - - const HashSet<RefPtr<Widget> >* children = view->children(); - ASSERT(children); - - HashSet<RefPtr<Widget> >::const_iterator end = children->end(); - for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != end; ++it) { - Widget* widget = (*it).get(); - if (!widget->isPluginView()) - continue; - static_cast<PluginView*>(widget)->setJavaScriptPaused(paused); - } -} - void ScriptDebugServer::createCallFrameAndPauseIfNeeded(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber) { TextPosition0 textPosition(WTF::OneBasedNumber::fromOneBasedInt(lineNumber).convertToZeroBased(), WTF::ZeroBasedNumber::base()); m_currentCallFrame = JavaScriptCallFrame::create(debuggerCallFrame, m_currentCallFrame, sourceID, textPosition); - pauseIfNeeded(toPage(debuggerCallFrame.dynamicGlobalObject())); + pauseIfNeeded(debuggerCallFrame.dynamicGlobalObject()); } void ScriptDebugServer::updateCallFrameAndPauseIfNeeded(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber) @@ -451,15 +321,15 @@ void ScriptDebugServer::updateCallFrameAndPauseIfNeeded(const DebuggerCallFrame& TextPosition0 textPosition(WTF::OneBasedNumber::fromOneBasedInt(lineNumber).convertToZeroBased(), WTF::ZeroBasedNumber::base()); m_currentCallFrame->update(debuggerCallFrame, sourceID, textPosition); - pauseIfNeeded(toPage(debuggerCallFrame.dynamicGlobalObject())); + pauseIfNeeded(debuggerCallFrame.dynamicGlobalObject()); } -void ScriptDebugServer::pauseIfNeeded(Page* page) +void ScriptDebugServer::pauseIfNeeded(JSGlobalObject* dynamicGlobalObject) { if (m_paused) return; - - if (!page || !hasListenersInterestedInPage(page)) + + if (!getListenersForGlobalObject(dynamicGlobalObject)) return; bool pauseNow = m_pauseOnNextStatement; @@ -471,11 +341,9 @@ void ScriptDebugServer::pauseIfNeeded(Page* page) m_pauseOnCallFrame = 0; m_pauseOnNextStatement = false; m_paused = true; - m_pausedPage = page; - dispatchFunctionToListeners(&ScriptDebugServer::dispatchDidPause, page); - - setJavaScriptPaused(page->group(), true); + dispatchFunctionToListeners(&ScriptDebugServer::dispatchDidPause, dynamicGlobalObject); + didPause(dynamicGlobalObject); TimerBase::fireTimersInNestedEventLoop(); @@ -484,12 +352,10 @@ void ScriptDebugServer::pauseIfNeeded(Page* page) while (!m_doneProcessingDebuggerEvents && !loop.ended()) loop.cycle(); - setJavaScriptPaused(page->group(), false); + didContinue(dynamicGlobalObject); + dispatchFunctionToListeners(&ScriptDebugServer::dispatchDidContinue, dynamicGlobalObject); m_paused = false; - m_pausedPage = 0; - - dispatchFunctionToListeners(&ScriptDebugServer::dispatchDidContinue, page); } void ScriptDebugServer::callEvent(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber) @@ -565,34 +431,6 @@ void ScriptDebugServer::recompileAllJSFunctionsSoon() m_recompileTimer.startOneShot(0); } -void ScriptDebugServer::recompileAllJSFunctions(Timer<ScriptDebugServer>*) -{ - JSLock lock(SilenceAssertionsOnly); - // If JavaScript stack is not empty postpone recompilation. - if (JSDOMWindow::commonJSGlobalData()->dynamicGlobalObject) - recompileAllJSFunctionsSoon(); - else - Debugger::recompileAllJSFunctions(JSDOMWindow::commonJSGlobalData()); -} - -void ScriptDebugServer::didAddListener(Page* page) -{ - recompileAllJSFunctionsSoon(); - page->setDebugger(this); -} - -void ScriptDebugServer::didRemoveListener(Page* page) -{ - if (hasListenersInterestedInPage(page)) - return; - - if (m_pausedPage == page) - m_doneProcessingDebuggerEvents = true; - - recompileAllJSFunctionsSoon(); - page->setDebugger(0); -} - } // namespace WebCore #endif // ENABLE(JAVASCRIPT_DEBUGGER) diff --git a/Source/WebCore/bindings/js/ScriptDebugServer.h b/Source/WebCore/bindings/js/ScriptDebugServer.h index e7e8502..e53cb4d 100644 --- a/Source/WebCore/bindings/js/ScriptDebugServer.h +++ b/Source/WebCore/bindings/js/ScriptDebugServer.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2008 Apple Inc. All rights reserved. - * Copyright (C) 2010 Google Inc. All rights reserved. + * Copyright (C) 2010-2011 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -50,21 +50,12 @@ class JSGlobalObject; } namespace WebCore { -class Frame; -class FrameView; -class Page; -class PageGroup; class ScriptDebugListener; class JavaScriptCallFrame; -class ScriptDebugServer : JSC::Debugger { +class ScriptDebugServer : protected JSC::Debugger { WTF_MAKE_NONCOPYABLE(ScriptDebugServer); WTF_MAKE_FAST_ALLOCATED; public: - static ScriptDebugServer& shared(); - - void addListener(ScriptDebugListener*, Page*); - void removeListener(ScriptDebugListener*, Page*); - String setBreakpoint(const String& sourceID, const ScriptBreakpoint&, int* actualLineNumber, int* actualColumnNumber); void removeBreakpoint(const String& breakpointId); void clearBreakpoints(); @@ -90,26 +81,24 @@ public: bool editScriptSource(const String& sourceID, const String& newContent, String& newSourceOrErrorMessage); void recompileAllJSFunctionsSoon(); - void recompileAllJSFunctions(Timer<ScriptDebugServer>* = 0); + virtual void recompileAllJSFunctions(Timer<ScriptDebugServer>* = 0) = 0; JavaScriptCallFrame* currentCallFrame(); -private: +protected: typedef HashSet<ScriptDebugListener*> ListenerSet; typedef void (ScriptDebugServer::*JavaScriptExecutionCallback)(ScriptDebugListener*); ScriptDebugServer(); ~ScriptDebugServer(); - bool hasBreakpoint(intptr_t sourceID, const TextPosition0& position) const; - bool hasListenersInterestedInPage(Page*); + virtual ListenerSet* getListenersForGlobalObject(JSC::JSGlobalObject*) = 0; + virtual void didPause(JSC::JSGlobalObject*) = 0; + virtual void didContinue(JSC::JSGlobalObject*) = 0; - void setJavaScriptPaused(const PageGroup&, bool paused); - void setJavaScriptPaused(Page*, bool paused); - void setJavaScriptPaused(Frame*, bool paused); - void setJavaScriptPaused(FrameView*, bool paused); + bool hasBreakpoint(intptr_t sourceID, const TextPosition0&) const; - void dispatchFunctionToListeners(JavaScriptExecutionCallback, Page*); + void dispatchFunctionToListeners(JavaScriptExecutionCallback, JSC::JSGlobalObject*); void dispatchFunctionToListeners(const ListenerSet& listeners, JavaScriptExecutionCallback callback); void dispatchDidPause(ScriptDebugListener*); void dispatchDidContinue(ScriptDebugListener*); @@ -118,7 +107,7 @@ private: void createCallFrameAndPauseIfNeeded(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineNumber); void updateCallFrameAndPauseIfNeeded(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineNumber); - void pauseIfNeeded(Page*); + void pauseIfNeeded(JSC::JSGlobalObject* dynamicGlobalObject); virtual void detach(JSC::JSGlobalObject*); @@ -131,9 +120,6 @@ private: virtual void didExecuteProgram(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineno); virtual void didReachBreakpoint(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineno); - void didAddListener(Page*); - void didRemoveListener(Page*); - typedef HashMap<Page*, ListenerSet*> PageListenersMap; typedef HashMap<long, ScriptBreakpoint> LineToBreakpointMap; typedef HashMap<intptr_t, LineToBreakpointMap> SourceIdToBreakpointsMap; @@ -143,7 +129,6 @@ private: PauseOnExceptionsState m_pauseOnExceptionsState; bool m_pauseOnNextStatement; bool m_paused; - Page* m_pausedPage; bool m_doneProcessingDebuggerEvents; bool m_breakpointsActivated; JavaScriptCallFrame* m_pauseOnCallFrame; diff --git a/Source/WebCore/bindings/js/ScriptHeapSnapshot.h b/Source/WebCore/bindings/js/ScriptHeapSnapshot.h index 6b40e20..a341ddc 100644 --- a/Source/WebCore/bindings/js/ScriptHeapSnapshot.h +++ b/Source/WebCore/bindings/js/ScriptHeapSnapshot.h @@ -50,7 +50,6 @@ public: unsigned int uid() const { return 0; } void writeJSON(OutputStream*) { } - int exactRetainedSize(uint64_t) { return -1; } private: ScriptHeapSnapshot() { } diff --git a/Source/WebCore/bindings/js/ScriptProfiler.cpp b/Source/WebCore/bindings/js/ScriptProfiler.cpp index f372c3c..3468ae3 100644 --- a/Source/WebCore/bindings/js/ScriptProfiler.cpp +++ b/Source/WebCore/bindings/js/ScriptProfiler.cpp @@ -30,11 +30,17 @@ #include "ScriptProfiler.h" +#include "GCController.h" #include "JSDOMBinding.h" #include <profiler/Profiler.h> namespace WebCore { +void ScriptProfiler::collectGarbage() +{ + gcController().garbageCollectNow(); +} + void ScriptProfiler::start(ScriptState* state, const String& title) { JSC::Profiler::profiler()->startProfiling(state, stringToUString(title)); diff --git a/Source/WebCore/bindings/js/ScriptProfiler.h b/Source/WebCore/bindings/js/ScriptProfiler.h index d8ad482..05d5e92 100644 --- a/Source/WebCore/bindings/js/ScriptProfiler.h +++ b/Source/WebCore/bindings/js/ScriptProfiler.h @@ -47,6 +47,7 @@ public: virtual bool isCanceled() = 0; }; + static void collectGarbage(); static void start(ScriptState* state, const String& title); static PassRefPtr<ScriptProfile> stop(ScriptState* state, const String& title); static PassRefPtr<ScriptHeapSnapshot> takeHeapSnapshot(const String&, HeapSnapshotProgress*) { return 0; } diff --git a/Source/WebCore/bindings/js/SerializedScriptValue.cpp b/Source/WebCore/bindings/js/SerializedScriptValue.cpp index b3d07ca..a9c1b24 100644 --- a/Source/WebCore/bindings/js/SerializedScriptValue.cpp +++ b/Source/WebCore/bindings/js/SerializedScriptValue.cpp @@ -206,6 +206,45 @@ protected: MarkedArgumentBuffer m_gcBuffer; }; +#if ASSUME_LITTLE_ENDIAN +template <typename T> static void writeLittleEndian(Vector<uint8_t>& buffer, T value) +{ + buffer.append(reinterpret_cast<uint8_t*>(&value), sizeof(value)); +} +#else +template <typename T> static void writeLittleEndian(Vector<uint8_t>& buffer, T value) +{ + for (unsigned i = 0; i < sizeof(T); i++) { + buffer.append(value & 0xFF); + value >>= 8; + } +} +#endif + +template <> void writeLittleEndian<uint8_t>(Vector<uint8_t>& buffer, uint8_t value) +{ + buffer.append(value); +} + +template <typename T> static bool writeLittleEndian(Vector<uint8_t>& buffer, const T* values, uint32_t length) +{ + if (length > numeric_limits<uint32_t>::max() / sizeof(T)) + return false; + +#if ASSUME_LITTLE_ENDIAN + buffer.append(reinterpret_cast<const uint8_t*>(values), length * sizeof(T)); +#else + for (unsigned i = 0; i < length; i++) { + T value = values[i]; + for (unsigned j = 0; j < sizeof(T); j++) { + buffer.append(static_cast<uint8_t>(value & 0xFF)); + value >>= 8; + } + } +#endif + return true; +} + class CloneSerializer : CloneBase { public: static bool serialize(ExecState* exec, JSValue value, Vector<uint8_t>& out) @@ -444,43 +483,6 @@ private: writeLittleEndian(m_buffer, c); } -#if ASSUME_LITTLE_ENDIAN - template <typename T> static void writeLittleEndian(Vector<uint8_t>& buffer, T value) - { - if (sizeof(T) == 1) - buffer.append(value); - else - buffer.append(reinterpret_cast<uint8_t*>(&value), sizeof(value)); - } -#else - template <typename T> static void writeLittleEndian(Vector<uint8_t>& buffer, T value) - { - for (unsigned i = 0; i < sizeof(T); i++) { - buffer.append(value & 0xFF); - value >>= 8; - } - } -#endif - - template <typename T> static bool writeLittleEndian(Vector<uint8_t>& buffer, const T* values, uint32_t length) - { - if (length > numeric_limits<uint32_t>::max() / sizeof(T)) - return false; - -#if ASSUME_LITTLE_ENDIAN - buffer.append(reinterpret_cast<const uint8_t*>(values), length * sizeof(T)); -#else - for (unsigned i = 0; i < length; i++) { - T value = values[i]; - for (unsigned j = 0; j < sizeof(T); j++) { - buffer.append(static_cast<uint8_t>(value & 0xFF)); - value >>= 8; - } - } -#endif - return true; - } - void write(uint32_t i) { writeLittleEndian(m_buffer, i); @@ -870,12 +872,7 @@ private: if (sizeof(T) == 1) value = *ptr++; else { -#if CPU(ARMV5_OR_LOWER) - // To protect misaligned memory access. - memcpy(&value, ptr, sizeof(T)); -#else value = *reinterpret_cast<const T*>(ptr); -#endif ptr += sizeof(T); } return true; @@ -968,14 +965,7 @@ private: return false; #if ASSUME_LITTLE_ENDIAN -#if CPU(ARMV5_OR_LOWER) - // To protect misaligned memory access. - Vector<UChar> alignedBuffer(length); - memcpy(alignedBuffer.data(), ptr, length * sizeof(UChar)); - str = UString::adopt(alignedBuffer); -#else str = UString(reinterpret_cast<const UChar*>(ptr), length); -#endif ptr += length * sizeof(UChar); #else Vector<UChar> buffer; @@ -1176,7 +1166,9 @@ private: CachedStringRef flags; if (!readStringData(flags)) return JSValue(); - RefPtr<RegExp> regExp = RegExp::create(&m_exec->globalData(), pattern->ustring(), flags->ustring()); + RegExpFlags reFlags = regExpFlags(flags->ustring()); + ASSERT(reFlags != InvalidFlags); + RefPtr<RegExp> regExp = RegExp::create(&m_exec->globalData(), pattern->ustring(), reFlags); return new (m_exec) RegExpObject(m_exec->lexicalGlobalObject(), m_globalObject->regExpStructure(), regExp); } case ObjectReferenceTag: { diff --git a/Source/WebCore/bindings/js/WorkerScriptController.cpp b/Source/WebCore/bindings/js/WorkerScriptController.cpp index d392281..67b0441 100644 --- a/Source/WebCore/bindings/js/WorkerScriptController.cpp +++ b/Source/WebCore/bindings/js/WorkerScriptController.cpp @@ -73,13 +73,13 @@ void WorkerScriptController::initScript() // Explicitly protect the global object's prototype so it isn't collected // when we allocate the global object. (Once the global object is fully // constructed, it can mark its own prototype.) - RefPtr<Structure> workerContextPrototypeStructure = JSWorkerContextPrototype::createStructure(jsNull()); + RefPtr<Structure> workerContextPrototypeStructure = JSWorkerContextPrototype::createStructure(*m_globalData, jsNull()); Global<JSWorkerContextPrototype> workerContextPrototype(*m_globalData, new (m_globalData.get()) JSWorkerContextPrototype(0, workerContextPrototypeStructure.release())); if (m_workerContext->isDedicatedWorkerContext()) { - RefPtr<Structure> dedicatedContextPrototypeStructure = JSDedicatedWorkerContextPrototype::createStructure(workerContextPrototype.get()); + RefPtr<Structure> dedicatedContextPrototypeStructure = JSDedicatedWorkerContextPrototype::createStructure(*m_globalData, workerContextPrototype.get()); Global<JSDedicatedWorkerContextPrototype> dedicatedContextPrototype(*m_globalData, new (m_globalData.get()) JSDedicatedWorkerContextPrototype(0, dedicatedContextPrototypeStructure.release())); - RefPtr<Structure> structure = JSDedicatedWorkerContext::createStructure(dedicatedContextPrototype.get()); + RefPtr<Structure> structure = JSDedicatedWorkerContext::createStructure(*m_globalData, dedicatedContextPrototype.get()); m_workerContextWrapper.set(*m_globalData, new (m_globalData.get()) JSDedicatedWorkerContext(structure.release(), m_workerContext->toDedicatedWorkerContext())); workerContextPrototype->putAnonymousValue(*m_globalData, 0, m_workerContextWrapper.get()); @@ -87,9 +87,9 @@ void WorkerScriptController::initScript() #if ENABLE(SHARED_WORKERS) } else { ASSERT(m_workerContext->isSharedWorkerContext()); - RefPtr<Structure> sharedContextPrototypeStructure = JSSharedWorkerContextPrototype::createStructure(workerContextPrototype.get()); + RefPtr<Structure> sharedContextPrototypeStructure = JSSharedWorkerContextPrototype::createStructure(*m_globalData, workerContextPrototype.get()); Global<JSSharedWorkerContextPrototype> sharedContextPrototype(*m_globalData, new (m_globalData.get()) JSSharedWorkerContextPrototype(0, sharedContextPrototypeStructure.release())); - RefPtr<Structure> structure = JSSharedWorkerContext::createStructure(sharedContextPrototype.get()); + RefPtr<Structure> structure = JSSharedWorkerContext::createStructure(*m_globalData, sharedContextPrototype.get()); m_workerContextWrapper.set(*m_globalData, new (m_globalData.get()) JSSharedWorkerContext(structure.release(), m_workerContext->toSharedWorkerContext())); workerContextPrototype->putAnonymousValue(*m_globalData, 0, m_workerContextWrapper.get()); diff --git a/Source/WebCore/bindings/js/WorkerScriptDebugServer.cpp b/Source/WebCore/bindings/js/WorkerScriptDebugServer.cpp new file mode 100755 index 0000000..5e2acd2 --- /dev/null +++ b/Source/WebCore/bindings/js/WorkerScriptDebugServer.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2011 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 "WorkerScriptDebugServer.h" + +#if ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(WORKERS) + +#include "WorkerContext.h" + +namespace WebCore { + +WorkerScriptDebugServer::WorkerScriptDebugServer() + : ScriptDebugServer() +{ +} + +void WorkerScriptDebugServer::addListener(ScriptDebugListener*, WorkerContext*) +{ +} + +void WorkerScriptDebugServer::removeListener(ScriptDebugListener*, WorkerContext*) +{ +} + +} // namespace WebCore + +#endif // ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(WORKERS) diff --git a/Source/WebCore/bindings/js/WorkerScriptDebugServer.h b/Source/WebCore/bindings/js/WorkerScriptDebugServer.h new file mode 100755 index 0000000..4062435 --- /dev/null +++ b/Source/WebCore/bindings/js/WorkerScriptDebugServer.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2011 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 WorkerScriptDebugServer_h +#define WorkerScriptDebugServer_h + +#if ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(WORKERS) + +#include "ScriptDebugServer.h" + +namespace WebCore { + +class WorkerContext; + +class WorkerScriptDebugServer : public ScriptDebugServer { + WTF_MAKE_NONCOPYABLE(WorkerScriptDebugServer); +public: + WorkerScriptDebugServer(); + ~WorkerScriptDebugServer() { } + + void addListener(ScriptDebugListener*, WorkerContext*); + void removeListener(ScriptDebugListener*, WorkerContext*); + +private: + virtual void recompileAllJSFunctions(Timer<ScriptDebugServer>*) { } + virtual ListenerSet* getListenersForGlobalObject(JSC::JSGlobalObject*) { return 0; } + virtual void didPause(JSC::JSGlobalObject*) { } + virtual void didContinue(JSC::JSGlobalObject*) { } +}; + +} // namespace WebCore + +#endif // ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(WORKERS) + +#endif // WorkerScriptDebugServer_h diff --git a/Source/WebCore/bindings/objc/DOMHTML.mm b/Source/WebCore/bindings/objc/DOMHTML.mm index a2277d2..92588e1 100644 --- a/Source/WebCore/bindings/objc/DOMHTML.mm +++ b/Source/WebCore/bindings/objc/DOMHTML.mm @@ -182,8 +182,7 @@ - (BOOL)_isEdited { - WebCore::RenderObject *renderer = core(self)->renderer(); - return renderer && [self _isTextField] && static_cast<WebCore::RenderTextControl *>(renderer)->lastChangeWasUserEdit(); + return core(self)->lastChangeWasUserEdit(); } @end @@ -192,8 +191,7 @@ - (BOOL)_isEdited { - WebCore::RenderObject* renderer = core(self)->renderer(); - return renderer && static_cast<WebCore::RenderTextControl*>(renderer)->lastChangeWasUserEdit(); + return core(self)->lastChangeWasUserEdit(); } @end diff --git a/Source/WebCore/bindings/scripts/CodeGeneratorGObject.pm b/Source/WebCore/bindings/scripts/CodeGeneratorGObject.pm index ed76d08..3806b75 100644 --- a/Source/WebCore/bindings/scripts/CodeGeneratorGObject.pm +++ b/Source/WebCore/bindings/scripts/CodeGeneratorGObject.pm @@ -459,89 +459,6 @@ EOF push(@txtInstallProps, "#endif /* ${conditionalString} */\n") if $conditionalString; } -my %breakWords = ("before" => 1, "can" => 1, "context" => 1, "dbl" => 1, "drag" => 1, - "drag" => 1, "duration" => 1, "has" => 1, "key" => 1, "loaded" => 1, - "mouse" => 1, "page" => 1, "pop" => 1, "rate" => 1, "select" => 1, - "time" => 1, "touch" => 1, "volume" => 1); - -sub SplitEventListenerAttrName { - my $attrName = shift; - - my @matches = grep { $attrName =~ /^$_/ } keys (%breakWords); - - if (@matches && (length $matches[0] < length $attrName)) { - $attrName = $matches[0] . "-" . substr($attrName, length $matches[0]); - } - - return $attrName; -} - -sub EventSignalName { - my $attrName = shift; - my $name = SplitEventListenerAttrName($attrName) . "-event"; - - return $name; -} - -sub GenerateEventListener { - my $name = shift; - my $object = shift; - my $interfaceName = shift; - - my $gobjectSignalName = EventSignalName($name); - - my $txtInstallSignal = << "EOF"; - g_signal_new("${gobjectSignalName}", - G_TYPE_FROM_CLASS(gobjectClass), - G_SIGNAL_RUN_LAST, - 0, - g_signal_accumulator_true_handled, 0, - webkit_marshal_BOOLEAN__OBJECT, - G_TYPE_BOOLEAN, 1, - WEBKIT_TYPE_DOM_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); - -EOF - push(@txtInstallSignals, $txtInstallSignal); - - my ${listenerName} = $name . "Listener"; - - my $txtInstallEventListener = << "EOF"; - WebCore::GObjectEventListener::addEventListener(object, coreObject, "${name}", "${gobjectSignalName}"); -EOF - push(@txtInstallEventListeners, $txtInstallEventListener); - - $implIncludes{"webkit/WebKitDOMEvent.h"} = 1; - $implIncludes{"GObjectEventListener.h"} = 1; -} - -my @eventSignalNames = ( - # User Interface Event types - "focus", "blur", - # Basic Event types - "load", "unload", "abort", "error", "select", "change", "formchange", "submit", "reset", - "resize", "scroll", - # Mouse Event types - "click", "dblclick", "mousedown", "mouseup", - "mousemove", "mouseover", "mouseout", - # Mouse Wheel Event types - "mousewheel", - # Keyboard Event types - "keydown", "keypress", "keyup", - # -- Events not in the spec but defined in WebKit - # Media Event types, - "loadstart", "progress", "suspend", "emptied", "stalled", "play", - "loadedmetadata", "loadeddata", "waiting", "playing", "canplay", - "canplaythrough", "seeking", "seeked", "timeupdate", "ended", - "ratechange", "durationchange", "volumechange", - # Drag and Drop Event types - "drag", "dragend", "dragenter", "dragleave", "dragover", "dragstart", "drop", - # Cut and Paste Event types - "beforecut", "cut", "beforecopy", "copy", "beforepaste", "paste", - # Animations - "webkitanimationend", "webkitanimationstart", "webkitanimationiteration", - # Other - "contextmenu", "input", "forminput", "invalid", "search", "selectstart"); - sub GenerateProperties { my ($object, $interfaceName, $dataNode) = @_; @@ -610,15 +527,6 @@ EOF } } - # We need to define all the events there are in all base classes - # that implement EventTarget. For now we only care about these - # two. - if ($interfaceName eq "Node" || $interfaceName eq "DOMWindow") { - foreach my $signalName (@eventSignalNames) { - GenerateEventListener($signalName, $object, $interfaceName); - } - } - push(@cBodyPriv, "};\n\n"); $txtGetProp = << "EOF"; @@ -669,13 +577,6 @@ static void ${lowerCaseIfaceName}_constructed(GObject* object) EOF push(@cBodyPriv, $implContent); - if (scalar @txtInstallEventListeners > 0) { - $implContent = << "EOF"; - WebCore::${interfaceName}* coreObject = static_cast<WebCore::${interfaceName}*>(WEBKIT_DOM_OBJECT(object)->coreObject); -EOF - push(@cBodyPriv, $implContent); - } - $implContent = << "EOF"; @txtInstallEventListeners if (G_OBJECT_CLASS(${lowerCaseIfaceName}_parent_class)->constructed) @@ -833,8 +734,7 @@ sub GenerateFunction { foreach my $param (@{$function->parameters}) { my $paramIDLType = $param->type; if ($paramIDLType eq "EventListener" || $paramIDLType eq "MediaQueryListListener") { - push(@hBody, "\n/* TODO: event function ${functionName} */\n\n"); - push(@cBody, "\n/* TODO: event function ${functionName} */\n\n"); + # EventListeners are handled elsewhere. return; } addIncludeInBody($paramIDLType); @@ -1283,6 +1183,7 @@ sub GenerateEventTargetIface { my $interfaceName = $dataNode->name; my $decamelize = FixUpDecamelizedName(decamelize($interfaceName)); + $implIncludes{"GObjectEventListener.h"} = 1; $implIncludes{"WebKitDOMEventTarget.h"} = 1; $implIncludes{"WebKitDOMEventPrivate.h"} = 1; @@ -1301,9 +1202,23 @@ static void webkit_dom_${decamelize}_dispatch_event(WebKitDOMEventTarget* target } } +static gboolean webkit_dom_${decamelize}_add_event_listener(WebKitDOMEventTarget* target, const char* eventName, GCallback handler, gboolean bubble, gpointer userData) +{ + WebCore::${interfaceName}* coreTarget = static_cast<WebCore::${interfaceName}*>(WEBKIT_DOM_OBJECT(target)->coreObject); + return WebCore::GObjectEventListener::addEventListener(G_OBJECT(target), coreTarget, eventName, handler, bubble, userData); +} + +static gboolean webkit_dom_${decamelize}_remove_event_listener(WebKitDOMEventTarget* target, const char* eventName, GCallback handler, gboolean bubble) +{ + WebCore::${interfaceName}* coreTarget = static_cast<WebCore::${interfaceName}*>(WEBKIT_DOM_OBJECT(target)->coreObject); + return WebCore::GObjectEventListener::removeEventListener(G_OBJECT(target), coreTarget, eventName, handler, bubble); +} + static void webkit_dom_event_target_init(WebKitDOMEventTargetIface* iface) { iface->dispatch_event = webkit_dom_${decamelize}_dispatch_event; + iface->add_event_listener = webkit_dom_${decamelize}_add_event_listener; + iface->remove_event_listener = webkit_dom_${decamelize}_remove_event_listener; } EOF diff --git a/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm b/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm index cb51c8a..12b477b 100644 --- a/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm +++ b/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm @@ -746,9 +746,9 @@ sub GenerateHeader $structureFlags{"JSC::NeedsThisConversion"} = 1; } push(@headerContent, - " static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype)\n" . + " static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)\n" . " {\n" . - " return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info);\n" . + " return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info);\n" . " }\n\n"); # markChildren function @@ -958,9 +958,9 @@ sub GenerateHeader $structureFlags{"JSC::OverridesMarkChildren"} = 1; } push(@headerContent, - " static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype)\n" . + " static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)\n" . " {\n" . - " return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info);\n" . + " return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info);\n" . " }\n"); if ($dataNode->extendedAttributes->{"DelegatingPrototypePutFunction"}) { push(@headerContent, " virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);\n"); @@ -1442,9 +1442,9 @@ sub GenerateImplementation push(@implContent, "JSObject* ${className}::createPrototype(ExecState* exec, JSGlobalObject* globalObject)\n"); push(@implContent, "{\n"); if ($hasParent && $parentClassName ne "JSC::DOMNodeFilter") { - push(@implContent, " return new (exec) ${className}Prototype(globalObject, ${className}Prototype::createStructure(${parentClassName}Prototype::self(exec, globalObject)));\n"); + push(@implContent, " return new (exec) ${className}Prototype(globalObject, ${className}Prototype::createStructure(exec->globalData(), ${parentClassName}Prototype::self(exec, globalObject)));\n"); } else { - push(@implContent, " return new (exec) ${className}Prototype(globalObject, ${className}Prototype::createStructure(globalObject->objectPrototype()));\n"); + push(@implContent, " return new (exec) ${className}Prototype(globalObject, ${className}Prototype::createStructure(globalObject->globalData(), globalObject->objectPrototype()));\n"); } push(@implContent, "}\n\n"); } @@ -2873,9 +2873,9 @@ sub GenerateConstructorDeclaration push(@$outputArray, " virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);\n"); push(@$outputArray, " static const JSC::ClassInfo s_info;\n"); - push(@$outputArray, " static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype)\n"); + push(@$outputArray, " static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)\n"); push(@$outputArray, " {\n"); - push(@$outputArray, " return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info);\n"); + push(@$outputArray, " return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info);\n"); push(@$outputArray, " }\n"); push(@$outputArray, "protected:\n"); @@ -2907,7 +2907,7 @@ sub GenerateConstructorDefinition push(@$outputArray, "const ClassInfo ${constructorClassName}::s_info = { \"${visibleClassName}Constructor\", &DOMConstructorObject::s_info, &${constructorClassName}Table, 0 };\n\n"); push(@$outputArray, "${constructorClassName}::${constructorClassName}(ExecState* exec, JSDOMGlobalObject* globalObject)\n"); - push(@$outputArray, " : DOMConstructorObject(${constructorClassName}::createStructure(globalObject->objectPrototype()), globalObject)\n"); + push(@$outputArray, " : DOMConstructorObject(${constructorClassName}::createStructure(globalObject->globalData(), globalObject->objectPrototype()), globalObject)\n"); push(@$outputArray, "{\n"); push(@$outputArray, " ASSERT(inherits(&s_info));\n"); if ($interfaceName eq "DOMWindow") { diff --git a/Source/WebCore/bindings/scripts/CodeGeneratorV8.pm b/Source/WebCore/bindings/scripts/CodeGeneratorV8.pm index df1c04a..6fc0b9a 100644 --- a/Source/WebCore/bindings/scripts/CodeGeneratorV8.pm +++ b/Source/WebCore/bindings/scripts/CodeGeneratorV8.pm @@ -128,7 +128,7 @@ sub AddIncludesForType # When we're finished with the one-file-per-class # reorganization, we won't need these special cases. - if (!$codeGenerator->IsPrimitiveType($type) and !$codeGenerator->AvoidInclusionOfType($type) and $type ne "Date") { + if (!$codeGenerator->IsPrimitiveType($type) and !$codeGenerator->IsStringType($type) and !$codeGenerator->AvoidInclusionOfType($type) and $type ne "Date") { # default, include the same named file $implIncludes{GetV8HeaderName(${type})} = 1; @@ -1716,8 +1716,22 @@ sub GenerateImplementation my $toActive = IsActiveDomType($interfaceName) ? "${className}::toActiveDOMObject" : "0"; + # Find the super descriptor. + my $parentClass = ""; + my $parentClassTemplate = ""; + foreach (@{$dataNode->parents}) { + my $parent = $codeGenerator->StripModule($_); + if ($parent eq "EventTarget") { + next; + } + $implIncludes{"V8${parent}.h"} = 1; + $parentClass = "V8" . $parent; + $parentClassTemplate = $parentClass . "::GetTemplate()"; + last; + } push(@implContentDecls, "namespace WebCore {\n\n"); - push(@implContentDecls, "WrapperTypeInfo ${className}::info = { ${className}::GetTemplate, ${className}::derefObject, ${toActive} };\n\n"); + my $parentClassInfo = $parentClass ? "&${parentClass}::info" : "0"; + push(@implContentDecls, "WrapperTypeInfo ${className}::info = { ${className}::GetTemplate, ${className}::derefObject, ${toActive}, ${parentClassInfo} };\n\n"); push(@implContentDecls, "namespace ${interfaceName}Internal {\n\n"); push(@implContentDecls, "template <typename T> void V8_USE(T) { }\n\n"); @@ -1941,15 +1955,6 @@ static v8::Persistent<v8::ObjectTemplate> ConfigureShadowObjectTemplate(v8::Pers END } - # find the super descriptor - my $parentClassTemplate = ""; - foreach (@{$dataNode->parents}) { - my $parent = $codeGenerator->StripModule($_); - if ($parent eq "EventTarget") { next; } - $implIncludes{"V8${parent}.h"} = 1; - $parentClassTemplate = "V8" . $parent . "::GetTemplate()"; - last; - } if (!$parentClassTemplate) { $parentClassTemplate = "v8::Persistent<v8::FunctionTemplate>()"; } @@ -2506,7 +2511,15 @@ END } push(@implContent, <<END); - ${domMapFunction}.set(impl, v8::Persistent<v8::Object>::New(wrapper)); + v8::Persistent<v8::Object> wrapperHandle = v8::Persistent<v8::Object>::New(wrapper); +END + if (IsNodeSubType($dataNode)) { + push(@implContent, <<END); + wrapperHandle.SetWrapperClassId(v8DOMSubtreeClassId); +END + } + push(@implContent, <<END); + ${domMapFunction}.set(impl, wrapperHandle); END push(@implContent, <<END); @@ -2833,6 +2846,7 @@ sub GetNativeType return "RefPtr<MediaQueryListListener>" if $type eq "MediaQueryListListener"; + return "PassRefPtr<DOMStringList>" if $type eq "DOMStringList" and $isParameter; return "RefPtr<DOMStringList>" if $type eq "DOMStringList"; # Default, assume native type is a pointer with same type name as idl type diff --git a/Source/WebCore/bindings/scripts/test/CPP/WebDOMTestCallback.cpp b/Source/WebCore/bindings/scripts/test/CPP/WebDOMTestCallback.cpp index 62ebc3c..d12d0c3 100644 --- a/Source/WebCore/bindings/scripts/test/CPP/WebDOMTestCallback.cpp +++ b/Source/WebCore/bindings/scripts/test/CPP/WebDOMTestCallback.cpp @@ -27,11 +27,13 @@ #include "Class1.h" #include "Class2.h" #include "Class3.h" +#include "DOMStringList.h" #include "KURL.h" #include "TestCallback.h" #include "WebDOMClass1.h" #include "WebDOMClass2.h" #include "WebDOMClass3.h" +#include "WebDOMDOMStringList.h" #include "WebDOMString.h" #include "WebExceptionHandler.h" #include "wtf/text/AtomicString.h" @@ -115,6 +117,14 @@ int WebDOMTestCallback::callbackWithNonBoolReturnType(const WebDOMClass3& class3 return impl()->callbackWithNonBoolReturnType(toWebCore(class3Param)); } +bool WebDOMTestCallback::callbackWithStringList(const WebDOMDOMStringList& listParam) +{ + if (!impl()) + return false; + + return impl()->callbackWithStringList(toWebCore(listParam)); +} + WebCore::TestCallback* toWebCore(const WebDOMTestCallback& wrapper) { return wrapper.impl(); diff --git a/Source/WebCore/bindings/scripts/test/CPP/WebDOMTestCallback.h b/Source/WebCore/bindings/scripts/test/CPP/WebDOMTestCallback.h index 7a077e2..8d11a4b 100644 --- a/Source/WebCore/bindings/scripts/test/CPP/WebDOMTestCallback.h +++ b/Source/WebCore/bindings/scripts/test/CPP/WebDOMTestCallback.h @@ -37,6 +37,7 @@ class WebDOMClass2; class WebDOMClass3; class WebDOMClass5; class WebDOMClass6; +class WebDOMDOMStringList; class WebDOMTestCallback : public WebDOMObject { public: @@ -51,6 +52,7 @@ public: bool callbackWithClass2Param(const WebDOMClass2& class2Param, const WebDOMString& strArg); int callbackWithNonBoolReturnType(const WebDOMClass3& class3Param); int customCallback(const WebDOMClass5& class5Param, const WebDOMClass6& class6Param); + bool callbackWithStringList(const WebDOMDOMStringList& listParam); WebCore::TestCallback* impl() const; diff --git a/Source/WebCore/bindings/scripts/test/GObject/WebKitDOMTestCallback.cpp b/Source/WebCore/bindings/scripts/test/GObject/WebKitDOMTestCallback.cpp index 054dc38..b63f50e 100644 --- a/Source/WebCore/bindings/scripts/test/GObject/WebKitDOMTestCallback.cpp +++ b/Source/WebCore/bindings/scripts/test/GObject/WebKitDOMTestCallback.cpp @@ -37,6 +37,8 @@ #include "webkit/WebKitDOMClass2Private.h" #include "webkit/WebKitDOMClass3.h" #include "webkit/WebKitDOMClass3Private.h" +#include "webkit/WebKitDOMDOMStringList.h" +#include "webkit/WebKitDOMDOMStringListPrivate.h" #include "webkit/WebKitDOMTestCallback.h" #include "webkit/WebKitDOMTestCallbackPrivate.h" #include "webkitdefines.h" @@ -117,6 +119,22 @@ webkit_dom_test_callback_callback_with_non_bool_return_type(WebKitDOMTestCallbac return res; } +gboolean +webkit_dom_test_callback_callback_with_string_list(WebKitDOMTestCallback* self, WebKitDOMDOMStringList* list_param) +{ + g_return_val_if_fail(self, 0); + WebCore::JSMainThreadNullState state; + WebCore::TestCallback * item = WebKit::core(self); + g_return_val_if_fail(list_param, 0); + WebCore::DOMStringList * converted_list_param = NULL; + if (list_param != NULL) { + converted_list_param = WebKit::core(list_param); + g_return_val_if_fail(converted_list_param, 0); + } + gboolean res = item->callbackWithStringList(converted_list_param); + return res; +} + G_DEFINE_TYPE(WebKitDOMTestCallback, webkit_dom_test_callback, WEBKIT_TYPE_DOM_OBJECT) diff --git a/Source/WebCore/bindings/scripts/test/GObject/WebKitDOMTestCallback.h b/Source/WebCore/bindings/scripts/test/GObject/WebKitDOMTestCallback.h index 6049c79..541afb2 100644 --- a/Source/WebCore/bindings/scripts/test/GObject/WebKitDOMTestCallback.h +++ b/Source/WebCore/bindings/scripts/test/GObject/WebKitDOMTestCallback.h @@ -58,6 +58,9 @@ webkit_dom_test_callback_callback_with_class2param(WebKitDOMTestCallback* self, WEBKIT_API glong webkit_dom_test_callback_callback_with_non_bool_return_type(WebKitDOMTestCallback* self, WebKitDOMClass3* class3param); +WEBKIT_API gboolean +webkit_dom_test_callback_callback_with_string_list(WebKitDOMTestCallback* self, WebKitDOMDOMStringList* list_param); + G_END_DECLS #endif /* WebKitDOMTestCallback_h */ diff --git a/Source/WebCore/bindings/scripts/test/GObject/WebKitDOMTestObj.cpp b/Source/WebCore/bindings/scripts/test/GObject/WebKitDOMTestObj.cpp index 44d58d4..1f81c5d 100644 --- a/Source/WebCore/bindings/scripts/test/GObject/WebKitDOMTestObj.cpp +++ b/Source/WebCore/bindings/scripts/test/GObject/WebKitDOMTestObj.cpp @@ -250,12 +250,6 @@ webkit_dom_test_obj_method_with_exception(WebKitDOMTestObj* self, GError **error } } - -/* TODO: event function webkit_dom_test_obj_add_event_listener */ - - -/* TODO: event function webkit_dom_test_obj_remove_event_listener */ - void webkit_dom_test_obj_with_dynamic_frame(WebKitDOMTestObj* self) { diff --git a/Source/WebCore/bindings/scripts/test/GObject/WebKitDOMTestObj.h b/Source/WebCore/bindings/scripts/test/GObject/WebKitDOMTestObj.h index 0416664..0f0f3c1 100644 --- a/Source/WebCore/bindings/scripts/test/GObject/WebKitDOMTestObj.h +++ b/Source/WebCore/bindings/scripts/test/GObject/WebKitDOMTestObj.h @@ -82,12 +82,6 @@ webkit_dom_test_obj_options_object(WebKitDOMTestObj* self, WebKitDOMOptionsObjec WEBKIT_API void webkit_dom_test_obj_method_with_exception(WebKitDOMTestObj* self, GError **error); - -/* TODO: event function webkit_dom_test_obj_add_event_listener */ - - -/* TODO: event function webkit_dom_test_obj_remove_event_listener */ - WEBKIT_API void webkit_dom_test_obj_with_dynamic_frame(WebKitDOMTestObj* self); diff --git a/Source/WebCore/bindings/scripts/test/JS/JSTestCallback.cpp b/Source/WebCore/bindings/scripts/test/JS/JSTestCallback.cpp index 1f48ee9..a5234d9 100644 --- a/Source/WebCore/bindings/scripts/test/JS/JSTestCallback.cpp +++ b/Source/WebCore/bindings/scripts/test/JS/JSTestCallback.cpp @@ -26,6 +26,7 @@ #include "JSClass1.h" #include "JSClass2.h" +#include "JSDOMStringList.h" #include "ScriptExecutionContext.h" #include <runtime/JSLock.h> #include <wtf/MainThread.h> @@ -110,6 +111,24 @@ bool JSTestCallback::callbackWithClass2Param(Class2* class2Param, const String& return !raisedException; } +bool JSTestCallback::callbackWithStringList(DOMStringList* listParam) +{ + if (!canInvokeCallback()) + return true; + + RefPtr<JSTestCallback> protect(this); + + JSLock lock(SilenceAssertionsOnly); + + ExecState* exec = m_data->globalObject()->globalExec(); + MarkedArgumentBuffer args; + args.append(toJS(exec, listParam)); + + bool raisedException = false; + m_data->invokeCallback(args, &raisedException); + return !raisedException; +} + } #endif // ENABLE(DATABASE) diff --git a/Source/WebCore/bindings/scripts/test/JS/JSTestCallback.h b/Source/WebCore/bindings/scripts/test/JS/JSTestCallback.h index ba3559c..226e874 100644 --- a/Source/WebCore/bindings/scripts/test/JS/JSTestCallback.h +++ b/Source/WebCore/bindings/scripts/test/JS/JSTestCallback.h @@ -45,6 +45,7 @@ public: virtual bool callbackWithClass2Param(Class2* class2Param, const String& strArg); COMPILE_ASSERT(false) virtual int callbackWithNonBoolReturnType(Class3* class3Param); virtual int customCallback(Class5* class5Param, Class6* class6Param); + virtual bool callbackWithStringList(DOMStringList* listParam); private: JSTestCallback(JSC::JSObject* callback, JSDOMGlobalObject*); diff --git a/Source/WebCore/bindings/scripts/test/JS/JSTestInterface.cpp b/Source/WebCore/bindings/scripts/test/JS/JSTestInterface.cpp index 8d519f5..ce0fef6 100644 --- a/Source/WebCore/bindings/scripts/test/JS/JSTestInterface.cpp +++ b/Source/WebCore/bindings/scripts/test/JS/JSTestInterface.cpp @@ -69,9 +69,9 @@ public: virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&); virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&); static const JSC::ClassInfo s_info; - static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) + static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype) { - return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: static const unsigned StructureFlags = JSC::OverridesGetOwnPropertySlot | JSC::ImplementsHasInstance | DOMConstructorObject::StructureFlags; @@ -82,7 +82,7 @@ protected: const ClassInfo JSTestInterfaceConstructor::s_info = { "TestInterfaceConstructor", &DOMConstructorObject::s_info, &JSTestInterfaceConstructorTable, 0 }; JSTestInterfaceConstructor::JSTestInterfaceConstructor(ExecState* exec, JSDOMGlobalObject* globalObject) - : DOMConstructorObject(JSTestInterfaceConstructor::createStructure(globalObject->objectPrototype()), globalObject) + : DOMConstructorObject(JSTestInterfaceConstructor::createStructure(globalObject->globalData(), globalObject->objectPrototype()), globalObject) { ASSERT(inherits(&s_info)); putDirect(exec->globalData(), exec->propertyNames().prototype, JSTestInterfacePrototype::self(exec, globalObject), DontDelete | ReadOnly); @@ -144,7 +144,7 @@ JSTestInterface::JSTestInterface(NonNullPassRefPtr<Structure> structure, JSDOMGl JSObject* JSTestInterface::createPrototype(ExecState* exec, JSGlobalObject* globalObject) { - return new (exec) JSTestInterfacePrototype(globalObject, JSTestInterfacePrototype::createStructure(globalObject->objectPrototype())); + return new (exec) JSTestInterfacePrototype(globalObject, JSTestInterfacePrototype::createStructure(globalObject->globalData(), globalObject->objectPrototype())); } bool JSTestInterface::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) diff --git a/Source/WebCore/bindings/scripts/test/JS/JSTestInterface.h b/Source/WebCore/bindings/scripts/test/JS/JSTestInterface.h index 2cabc23..5ee33a0 100644 --- a/Source/WebCore/bindings/scripts/test/JS/JSTestInterface.h +++ b/Source/WebCore/bindings/scripts/test/JS/JSTestInterface.h @@ -41,9 +41,9 @@ public: virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&); static const JSC::ClassInfo s_info; - static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) + static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype) { - return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*); @@ -63,9 +63,9 @@ class JSTestInterfacePrototype : public JSC::JSObjectWithGlobalObject { public: static JSC::JSObject* self(JSC::ExecState*, JSC::JSGlobalObject*); static const JSC::ClassInfo s_info; - static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) + static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype) { - return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } JSTestInterfacePrototype(JSC::JSGlobalObject* globalObject, NonNullPassRefPtr<JSC::Structure> structure) : JSC::JSObjectWithGlobalObject(globalObject, structure) { } protected: diff --git a/Source/WebCore/bindings/scripts/test/JS/JSTestMediaQueryListListener.cpp b/Source/WebCore/bindings/scripts/test/JS/JSTestMediaQueryListListener.cpp index 0e5edeb..efaee3b 100644 --- a/Source/WebCore/bindings/scripts/test/JS/JSTestMediaQueryListListener.cpp +++ b/Source/WebCore/bindings/scripts/test/JS/JSTestMediaQueryListListener.cpp @@ -70,9 +70,9 @@ public: virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&); virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&); static const JSC::ClassInfo s_info; - static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) + static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype) { - return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: static const unsigned StructureFlags = JSC::OverridesGetOwnPropertySlot | JSC::ImplementsHasInstance | DOMConstructorObject::StructureFlags; @@ -81,7 +81,7 @@ protected: const ClassInfo JSTestMediaQueryListListenerConstructor::s_info = { "TestMediaQueryListListenerConstructor", &DOMConstructorObject::s_info, &JSTestMediaQueryListListenerConstructorTable, 0 }; JSTestMediaQueryListListenerConstructor::JSTestMediaQueryListListenerConstructor(ExecState* exec, JSDOMGlobalObject* globalObject) - : DOMConstructorObject(JSTestMediaQueryListListenerConstructor::createStructure(globalObject->objectPrototype()), globalObject) + : DOMConstructorObject(JSTestMediaQueryListListenerConstructor::createStructure(globalObject->globalData(), globalObject->objectPrototype()), globalObject) { ASSERT(inherits(&s_info)); putDirect(exec->globalData(), exec->propertyNames().prototype, JSTestMediaQueryListListenerPrototype::self(exec, globalObject), DontDelete | ReadOnly); @@ -140,7 +140,7 @@ JSTestMediaQueryListListener::JSTestMediaQueryListListener(NonNullPassRefPtr<Str JSObject* JSTestMediaQueryListListener::createPrototype(ExecState* exec, JSGlobalObject* globalObject) { - return new (exec) JSTestMediaQueryListListenerPrototype(globalObject, JSTestMediaQueryListListenerPrototype::createStructure(globalObject->objectPrototype())); + return new (exec) JSTestMediaQueryListListenerPrototype(globalObject, JSTestMediaQueryListListenerPrototype::createStructure(globalObject->globalData(), globalObject->objectPrototype())); } bool JSTestMediaQueryListListener::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) diff --git a/Source/WebCore/bindings/scripts/test/JS/JSTestMediaQueryListListener.h b/Source/WebCore/bindings/scripts/test/JS/JSTestMediaQueryListListener.h index a9f8606..fdb8a02 100644 --- a/Source/WebCore/bindings/scripts/test/JS/JSTestMediaQueryListListener.h +++ b/Source/WebCore/bindings/scripts/test/JS/JSTestMediaQueryListListener.h @@ -39,9 +39,9 @@ public: virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&); static const JSC::ClassInfo s_info; - static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) + static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype) { - return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*); @@ -63,9 +63,9 @@ public: static const JSC::ClassInfo s_info; virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&); virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&); - static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) + static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype) { - return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } JSTestMediaQueryListListenerPrototype(JSC::JSGlobalObject* globalObject, NonNullPassRefPtr<JSC::Structure> structure) : JSC::JSObjectWithGlobalObject(globalObject, structure) { } protected: diff --git a/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp b/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp index fd2f4d9..a98cafa 100644 --- a/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp +++ b/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp @@ -149,9 +149,9 @@ public: virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&); virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&); static const JSC::ClassInfo s_info; - static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) + static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype) { - return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: static const unsigned StructureFlags = JSC::OverridesGetOwnPropertySlot | JSC::ImplementsHasInstance | DOMConstructorObject::StructureFlags; @@ -160,7 +160,7 @@ protected: const ClassInfo JSTestObjConstructor::s_info = { "TestObjConstructor", &DOMConstructorObject::s_info, &JSTestObjConstructorTable, 0 }; JSTestObjConstructor::JSTestObjConstructor(ExecState* exec, JSDOMGlobalObject* globalObject) - : DOMConstructorObject(JSTestObjConstructor::createStructure(globalObject->objectPrototype()), globalObject) + : DOMConstructorObject(JSTestObjConstructor::createStructure(globalObject->globalData(), globalObject->objectPrototype()), globalObject) { ASSERT(inherits(&s_info)); putDirect(exec->globalData(), exec->propertyNames().prototype, JSTestObjPrototype::self(exec, globalObject), DontDelete | ReadOnly); @@ -265,7 +265,7 @@ JSTestObj::JSTestObj(NonNullPassRefPtr<Structure> structure, JSDOMGlobalObject* JSObject* JSTestObj::createPrototype(ExecState* exec, JSGlobalObject* globalObject) { - return new (exec) JSTestObjPrototype(globalObject, JSTestObjPrototype::createStructure(globalObject->objectPrototype())); + return new (exec) JSTestObjPrototype(globalObject, JSTestObjPrototype::createStructure(globalObject->globalData(), globalObject->objectPrototype())); } bool JSTestObj::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) diff --git a/Source/WebCore/bindings/scripts/test/JS/JSTestObj.h b/Source/WebCore/bindings/scripts/test/JS/JSTestObj.h index 7e21168..751239b 100644 --- a/Source/WebCore/bindings/scripts/test/JS/JSTestObj.h +++ b/Source/WebCore/bindings/scripts/test/JS/JSTestObj.h @@ -40,9 +40,9 @@ public: virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&); static const JSC::ClassInfo s_info; - static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) + static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype) { - return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*); @@ -72,9 +72,9 @@ public: static const JSC::ClassInfo s_info; virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&); virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&); - static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) + static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype) { - return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } JSTestObjPrototype(JSC::JSGlobalObject* globalObject, NonNullPassRefPtr<JSC::Structure> structure) : JSC::JSObjectWithGlobalObject(globalObject, structure) { } protected: diff --git a/Source/WebCore/bindings/scripts/test/JS/JSTestSerializedScriptValueInterface.cpp b/Source/WebCore/bindings/scripts/test/JS/JSTestSerializedScriptValueInterface.cpp index 5dd6c44..535f99b 100644 --- a/Source/WebCore/bindings/scripts/test/JS/JSTestSerializedScriptValueInterface.cpp +++ b/Source/WebCore/bindings/scripts/test/JS/JSTestSerializedScriptValueInterface.cpp @@ -71,9 +71,9 @@ public: virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&); virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&); static const JSC::ClassInfo s_info; - static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) + static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype) { - return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: static const unsigned StructureFlags = JSC::OverridesGetOwnPropertySlot | JSC::ImplementsHasInstance | DOMConstructorObject::StructureFlags; @@ -82,7 +82,7 @@ protected: const ClassInfo JSTestSerializedScriptValueInterfaceConstructor::s_info = { "TestSerializedScriptValueInterfaceConstructor", &DOMConstructorObject::s_info, &JSTestSerializedScriptValueInterfaceConstructorTable, 0 }; JSTestSerializedScriptValueInterfaceConstructor::JSTestSerializedScriptValueInterfaceConstructor(ExecState* exec, JSDOMGlobalObject* globalObject) - : DOMConstructorObject(JSTestSerializedScriptValueInterfaceConstructor::createStructure(globalObject->objectPrototype()), globalObject) + : DOMConstructorObject(JSTestSerializedScriptValueInterfaceConstructor::createStructure(globalObject->globalData(), globalObject->objectPrototype()), globalObject) { ASSERT(inherits(&s_info)); putDirect(exec->globalData(), exec->propertyNames().prototype, JSTestSerializedScriptValueInterfacePrototype::self(exec, globalObject), DontDelete | ReadOnly); @@ -130,7 +130,7 @@ JSTestSerializedScriptValueInterface::JSTestSerializedScriptValueInterface(NonNu JSObject* JSTestSerializedScriptValueInterface::createPrototype(ExecState* exec, JSGlobalObject* globalObject) { - return new (exec) JSTestSerializedScriptValueInterfacePrototype(globalObject, JSTestSerializedScriptValueInterfacePrototype::createStructure(globalObject->objectPrototype())); + return new (exec) JSTestSerializedScriptValueInterfacePrototype(globalObject, JSTestSerializedScriptValueInterfacePrototype::createStructure(globalObject->globalData(), globalObject->objectPrototype())); } bool JSTestSerializedScriptValueInterface::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) diff --git a/Source/WebCore/bindings/scripts/test/JS/JSTestSerializedScriptValueInterface.h b/Source/WebCore/bindings/scripts/test/JS/JSTestSerializedScriptValueInterface.h index 175fb12..d5f8879 100644 --- a/Source/WebCore/bindings/scripts/test/JS/JSTestSerializedScriptValueInterface.h +++ b/Source/WebCore/bindings/scripts/test/JS/JSTestSerializedScriptValueInterface.h @@ -41,9 +41,9 @@ public: virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&); static const JSC::ClassInfo s_info; - static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) + static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype) { - return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*); @@ -63,9 +63,9 @@ class JSTestSerializedScriptValueInterfacePrototype : public JSC::JSObjectWithGl public: static JSC::JSObject* self(JSC::ExecState*, JSC::JSGlobalObject*); static const JSC::ClassInfo s_info; - static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) + static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype) { - return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } JSTestSerializedScriptValueInterfacePrototype(JSC::JSGlobalObject* globalObject, NonNullPassRefPtr<JSC::Structure> structure) : JSC::JSObjectWithGlobalObject(globalObject, structure) { } protected: diff --git a/Source/WebCore/bindings/scripts/test/ObjC/DOMTestCallback.h b/Source/WebCore/bindings/scripts/test/ObjC/DOMTestCallback.h index 08c30b7..3d6f7bd 100644 --- a/Source/WebCore/bindings/scripts/test/ObjC/DOMTestCallback.h +++ b/Source/WebCore/bindings/scripts/test/ObjC/DOMTestCallback.h @@ -33,6 +33,7 @@ @class DOMClass3; @class DOMClass5; @class DOMClass6; +@class DOMDOMStringList; @class NSString; @interface DOMTestCallback : DOMObject @@ -41,6 +42,7 @@ - (BOOL)callbackWithClass2Param:(DOMClass2 *)class2Param strArg:(NSString *)strArg; - (int)callbackWithNonBoolReturnType:(DOMClass3 *)class3Param; - (int)customCallback:(DOMClass5 *)class5Param class6Param:(DOMClass6 *)class6Param; +- (BOOL)callbackWithStringList:(DOMDOMStringList *)listParam; @end #endif diff --git a/Source/WebCore/bindings/scripts/test/ObjC/DOMTestCallback.mm b/Source/WebCore/bindings/scripts/test/ObjC/DOMTestCallback.mm index c4be39d..e070de5 100644 --- a/Source/WebCore/bindings/scripts/test/ObjC/DOMTestCallback.mm +++ b/Source/WebCore/bindings/scripts/test/ObjC/DOMTestCallback.mm @@ -45,8 +45,10 @@ #import "DOMClass3Internal.h" #import "DOMClass5Internal.h" #import "DOMClass6Internal.h" +#import "DOMDOMStringListInternal.h" #import "DOMEventInternal.h" #import "DOMNodeInternal.h" +#import "DOMStringList.h" #import "DOMStyleSheetInternal.h" #import "DOMTestCallbackInternal.h" #import "ExceptionHandlers.h" @@ -109,6 +111,12 @@ return IMPL->customCallback(core(class5Param), core(class6Param)); } +- (BOOL)callbackWithStringList:(DOMDOMStringList *)listParam +{ + WebCore::JSMainThreadNullState state; + return IMPL->callbackWithStringList(core(listParam)); +} + @end WebCore::TestCallback* core(DOMTestCallback *wrapper) diff --git a/Source/WebCore/bindings/scripts/test/TestCallback.idl b/Source/WebCore/bindings/scripts/test/TestCallback.idl index 9679a5a..2475251 100644 --- a/Source/WebCore/bindings/scripts/test/TestCallback.idl +++ b/Source/WebCore/bindings/scripts/test/TestCallback.idl @@ -38,5 +38,6 @@ module test { boolean callbackWithClass2Param(in Class2 class2Param, in DOMString strArg); long callbackWithNonBoolReturnType(in Class3 class3Param); [Custom] long customCallback(in Class5 class5Param, in Class6 class6Param); + boolean callbackWithStringList(in DOMStringList listParam); }; } diff --git a/Source/WebCore/bindings/scripts/test/V8/V8TestCallback.cpp b/Source/WebCore/bindings/scripts/test/V8/V8TestCallback.cpp index 057302d..c17f73d 100644 --- a/Source/WebCore/bindings/scripts/test/V8/V8TestCallback.cpp +++ b/Source/WebCore/bindings/scripts/test/V8/V8TestCallback.cpp @@ -27,7 +27,7 @@ #include "V8Class1.h" #include "V8Class2.h" #include "V8CustomVoidCallback.h" -#include "V8DOMString.h" +#include "V8DOMStringList.h" #include "V8Proxy.h" #include <wtf/GetPtr.h> #include <wtf/RefCounted.h> @@ -131,6 +131,33 @@ bool V8TestCallback::callbackWithClass2Param(Class2* class2Param, const String& return !invokeCallback(m_callback, 2, argv, callbackReturnValue, scriptExecutionContext()); } +bool V8TestCallback::callbackWithStringList(PassRefPtr<DOMStringList> listParam) +{ + if (!canInvokeCallback()) + return true; + + v8::HandleScope handleScope; + + v8::Handle<v8::Context> v8Context = toV8Context(scriptExecutionContext(), m_worldContext); + if (v8Context.IsEmpty()) + return true; + + v8::Context::Scope scope(v8Context); + + v8::Handle<v8::Value> listParamHandle = toV8(listParam); + if (listParamHandle.IsEmpty()) { + CRASH(); + return true; + } + + v8::Handle<v8::Value> argv[] = { + listParamHandle + }; + + bool callbackReturnValue = false; + return !invokeCallback(m_callback, 1, argv, callbackReturnValue, scriptExecutionContext()); +} + } // namespace WebCore #endif // ENABLE(DATABASE) diff --git a/Source/WebCore/bindings/scripts/test/V8/V8TestCallback.h b/Source/WebCore/bindings/scripts/test/V8/V8TestCallback.h index 8ff8c26..194f13c 100644 --- a/Source/WebCore/bindings/scripts/test/V8/V8TestCallback.h +++ b/Source/WebCore/bindings/scripts/test/V8/V8TestCallback.h @@ -50,6 +50,7 @@ public: virtual bool callbackWithClass2Param(Class2* class2Param, const String& strArg); COMPILE_ASSERT(false) virtual int callbackWithNonBoolReturnType(Class3* class3Param); virtual int customCallback(Class5* class5Param, Class6* class6Param); + virtual bool callbackWithStringList(PassRefPtr<DOMStringList> listParam); private: V8TestCallback(v8::Local<v8::Object>, ScriptExecutionContext*); diff --git a/Source/WebCore/bindings/scripts/test/V8/V8TestInterface.cpp b/Source/WebCore/bindings/scripts/test/V8/V8TestInterface.cpp index 4c40d98..21c8804 100644 --- a/Source/WebCore/bindings/scripts/test/V8/V8TestInterface.cpp +++ b/Source/WebCore/bindings/scripts/test/V8/V8TestInterface.cpp @@ -33,7 +33,7 @@ namespace WebCore { -WrapperTypeInfo V8TestInterface::info = { V8TestInterface::GetTemplate, V8TestInterface::derefObject, 0 }; +WrapperTypeInfo V8TestInterface::info = { V8TestInterface::GetTemplate, V8TestInterface::derefObject, 0, 0 }; namespace TestInterfaceInternal { @@ -87,7 +87,8 @@ v8::Handle<v8::Object> V8TestInterface::wrapSlow(TestInterface* impl) return wrapper; impl->ref(); - getDOMObjectMap().set(impl, v8::Persistent<v8::Object>::New(wrapper)); + v8::Persistent<v8::Object> wrapperHandle = v8::Persistent<v8::Object>::New(wrapper); + getDOMObjectMap().set(impl, wrapperHandle); return wrapper; } diff --git a/Source/WebCore/bindings/scripts/test/V8/V8TestMediaQueryListListener.cpp b/Source/WebCore/bindings/scripts/test/V8/V8TestMediaQueryListListener.cpp index ab9e6db..6d71ea7 100644 --- a/Source/WebCore/bindings/scripts/test/V8/V8TestMediaQueryListListener.cpp +++ b/Source/WebCore/bindings/scripts/test/V8/V8TestMediaQueryListListener.cpp @@ -33,7 +33,7 @@ namespace WebCore { -WrapperTypeInfo V8TestMediaQueryListListener::info = { V8TestMediaQueryListListener::GetTemplate, V8TestMediaQueryListListener::derefObject, 0 }; +WrapperTypeInfo V8TestMediaQueryListListener::info = { V8TestMediaQueryListListener::GetTemplate, V8TestMediaQueryListListener::derefObject, 0, 0 }; namespace TestMediaQueryListListenerInternal { @@ -94,7 +94,8 @@ v8::Handle<v8::Object> V8TestMediaQueryListListener::wrapSlow(TestMediaQueryList return wrapper; impl->ref(); - getDOMObjectMap().set(impl, v8::Persistent<v8::Object>::New(wrapper)); + v8::Persistent<v8::Object> wrapperHandle = v8::Persistent<v8::Object>::New(wrapper); + getDOMObjectMap().set(impl, wrapperHandle); return wrapper; } diff --git a/Source/WebCore/bindings/scripts/test/V8/V8TestObj.cpp b/Source/WebCore/bindings/scripts/test/V8/V8TestObj.cpp index 4298756..5884e89 100644 --- a/Source/WebCore/bindings/scripts/test/V8/V8TestObj.cpp +++ b/Source/WebCore/bindings/scripts/test/V8/V8TestObj.cpp @@ -46,7 +46,7 @@ namespace WebCore { -WrapperTypeInfo V8TestObj::info = { V8TestObj::GetTemplate, V8TestObj::derefObject, 0 }; +WrapperTypeInfo V8TestObj::info = { V8TestObj::GetTemplate, V8TestObj::derefObject, 0, 0 }; namespace TestObjInternal { @@ -1380,7 +1380,8 @@ v8::Handle<v8::Object> V8TestObj::wrapSlow(TestObj* impl) return wrapper; impl->ref(); - getDOMObjectMap().set(impl, v8::Persistent<v8::Object>::New(wrapper)); + v8::Persistent<v8::Object> wrapperHandle = v8::Persistent<v8::Object>::New(wrapper); + getDOMObjectMap().set(impl, wrapperHandle); return wrapper; } diff --git a/Source/WebCore/bindings/scripts/test/V8/V8TestSerializedScriptValueInterface.cpp b/Source/WebCore/bindings/scripts/test/V8/V8TestSerializedScriptValueInterface.cpp index fef8dbd..c6cc4d6 100644 --- a/Source/WebCore/bindings/scripts/test/V8/V8TestSerializedScriptValueInterface.cpp +++ b/Source/WebCore/bindings/scripts/test/V8/V8TestSerializedScriptValueInterface.cpp @@ -34,7 +34,7 @@ namespace WebCore { -WrapperTypeInfo V8TestSerializedScriptValueInterface::info = { V8TestSerializedScriptValueInterface::GetTemplate, V8TestSerializedScriptValueInterface::derefObject, 0 }; +WrapperTypeInfo V8TestSerializedScriptValueInterface::info = { V8TestSerializedScriptValueInterface::GetTemplate, V8TestSerializedScriptValueInterface::derefObject, 0, 0 }; namespace TestSerializedScriptValueInterfaceInternal { @@ -83,7 +83,8 @@ v8::Handle<v8::Object> V8TestSerializedScriptValueInterface::wrapSlow(TestSerial impl->ref(); SerializedScriptValue::deserializeAndSetProperty(wrapper, "value", static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly), impl->value()); - getDOMObjectMap().set(impl, v8::Persistent<v8::Object>::New(wrapper)); + v8::Persistent<v8::Object> wrapperHandle = v8::Persistent<v8::Object>::New(wrapper); + getDOMObjectMap().set(impl, wrapperHandle); return wrapper; } diff --git a/Source/WebCore/bindings/v8/DebuggerScript.js b/Source/WebCore/bindings/v8/DebuggerScript.js index 0bed33d..fe6e8ab 100644 --- a/Source/WebCore/bindings/v8/DebuggerScript.js +++ b/Source/WebCore/bindings/v8/DebuggerScript.js @@ -262,5 +262,4 @@ DebuggerScript._frameMirrorToJSCallFrame = function(frameMirror, callerFrame) } return DebuggerScript; - })(); diff --git a/Source/WebCore/bindings/v8/PageScriptDebugServer.cpp b/Source/WebCore/bindings/v8/PageScriptDebugServer.cpp new file mode 100755 index 0000000..f149d8f --- /dev/null +++ b/Source/WebCore/bindings/v8/PageScriptDebugServer.cpp @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2011 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 "PageScriptDebugServer.h" + +#if ENABLE(JAVASCRIPT_DEBUGGER) + +#include "Frame.h" +#include "Page.h" +#include "ScriptDebugListener.h" +#include "V8Binding.h" +#include "V8DOMWindow.h" +#include "V8Proxy.h" +#include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> +#include <wtf/StdLibExtras.h> + +namespace WebCore { + +static Frame* retrieveFrame(v8::Handle<v8::Context> context) +{ + if (context.IsEmpty()) + return 0; + + // Test that context has associated global dom window object. + v8::Handle<v8::Object> global = context->Global(); + if (global.IsEmpty()) + return 0; + + global = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), global); + if (global.IsEmpty()) + return 0; + + return V8Proxy::retrieveFrame(context); +} + +PageScriptDebugServer& PageScriptDebugServer::shared() +{ + DEFINE_STATIC_LOCAL(PageScriptDebugServer, server, ()); + return server; +} + +PageScriptDebugServer::PageScriptDebugServer() + : ScriptDebugServer() + , m_pausedPage(0) + , m_enabled(true) +{ +} + +void PageScriptDebugServer::addListener(ScriptDebugListener* listener, Page* page) +{ + if (!m_enabled) + return; + + V8Proxy* proxy = V8Proxy::retrieve(page->mainFrame()); + if (!proxy) + return; + + v8::HandleScope scope; + v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); + v8::Context::Scope contextScope(debuggerContext); + + if (!m_listenersMap.size()) { + ensureDebuggerScriptCompiled(); + ASSERT(!m_debuggerScript.get()->IsUndefined()); + v8::Debug::SetDebugEventListener2(&PageScriptDebugServer::v8DebugEventCallback, v8::External::New(this)); + } + m_listenersMap.set(page, listener); + + V8DOMWindowShell* shell = proxy->windowShell(); + if (!shell->isContextInitialized()) + return; + v8::Handle<v8::Context> context = shell->context(); + v8::Handle<v8::Function> getScriptsFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("getScripts"))); + v8::Handle<v8::Value> argv[] = { context->GetData() }; + v8::Handle<v8::Value> value = getScriptsFunction->Call(m_debuggerScript.get(), 1, argv); + if (value.IsEmpty()) + return; + ASSERT(!value->IsUndefined() && value->IsArray()); + v8::Handle<v8::Array> scriptsArray = v8::Handle<v8::Array>::Cast(value); + for (unsigned i = 0; i < scriptsArray->Length(); ++i) + dispatchDidParseSource(listener, v8::Handle<v8::Object>::Cast(scriptsArray->Get(v8::Integer::New(i)))); +} + +void PageScriptDebugServer::removeListener(ScriptDebugListener* listener, Page* page) +{ + if (!m_listenersMap.contains(page)) + return; + + if (m_pausedPage == page) + continueProgram(); + + m_listenersMap.remove(page); + + if (m_listenersMap.isEmpty()) + v8::Debug::SetDebugEventListener(0); + // FIXME: Remove all breakpoints set by the agent. +} + +void PageScriptDebugServer::setClientMessageLoop(PassOwnPtr<ClientMessageLoop> clientMessageLoop) +{ + m_clientMessageLoop = clientMessageLoop; +} + +ScriptDebugListener* PageScriptDebugServer::getDebugListenerForContext(v8::Handle<v8::Context> context) +{ + v8::HandleScope scope; + Frame* frame = retrieveFrame(context); + if (!frame) + return 0; + return m_listenersMap.get(frame->page()); +} + +void PageScriptDebugServer::runMessageLoopOnPause(v8::Handle<v8::Context> context) +{ + v8::HandleScope scope; + Frame* frame = retrieveFrame(context); + m_pausedPage = frame->page(); + + // Wait for continue or step command. + m_clientMessageLoop->run(m_pausedPage); + + // The listener may have been removed in the nested loop. + if (ScriptDebugListener* listener = m_listenersMap.get(m_pausedPage)) + listener->didContinue(); + + m_pausedPage = 0; +} + +void PageScriptDebugServer::quitMessageLoopOnPause() +{ + m_clientMessageLoop->quitNow(); +} + +} // namespace WebCore + +#endif // ENABLE(JAVASCRIPT_DEBUGGER) diff --git a/Source/WebCore/bindings/v8/PageScriptDebugServer.h b/Source/WebCore/bindings/v8/PageScriptDebugServer.h new file mode 100755 index 0000000..4b134c1 --- /dev/null +++ b/Source/WebCore/bindings/v8/PageScriptDebugServer.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2011 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 PageScriptDebugServer_h +#define PageScriptDebugServer_h + +#if ENABLE(JAVASCRIPT_DEBUGGER) + +#include "ScriptDebugServer.h" +#include <wtf/Forward.h> + +namespace WebCore { + +class Page; + +class PageScriptDebugServer : public ScriptDebugServer { + WTF_MAKE_NONCOPYABLE(PageScriptDebugServer); +public: + static PageScriptDebugServer& shared(); + + void addListener(ScriptDebugListener*, Page*); + void removeListener(ScriptDebugListener*, Page*); + + // v8-specific methods. + void setEnabled(bool value) { m_enabled = value; } + + class ClientMessageLoop { + public: + virtual ~ClientMessageLoop() { } + virtual void run(Page*) = 0; + virtual void quitNow() = 0; + }; + void setClientMessageLoop(PassOwnPtr<ClientMessageLoop>); + +private: + PageScriptDebugServer(); + virtual ~PageScriptDebugServer() { } + + virtual ScriptDebugListener* getDebugListenerForContext(v8::Handle<v8::Context>); + virtual void runMessageLoopOnPause(v8::Handle<v8::Context>); + virtual void quitMessageLoopOnPause(); + + typedef HashMap<Page*, ScriptDebugListener*> ListenersMap; + ListenersMap m_listenersMap; + OwnPtr<ClientMessageLoop> m_clientMessageLoop; + Page* m_pausedPage; + bool m_enabled; +}; + +} // namespace WebCore + +#endif // ENABLE(JAVASCRIPT_DEBUGGER) + +#endif // PageScriptDebugServer_h diff --git a/Source/WebCore/bindings/v8/RetainedDOMInfo.cpp b/Source/WebCore/bindings/v8/RetainedDOMInfo.cpp new file mode 100644 index 0000000..ba64263 --- /dev/null +++ b/Source/WebCore/bindings/v8/RetainedDOMInfo.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2011 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 "RetainedDOMInfo.h" + +#include "Node.h" + +namespace WebCore { + +RetainedDOMInfo::RetainedDOMInfo(Node* root) + : m_root(root) +{ + ASSERT(m_root); +} + +RetainedDOMInfo::~RetainedDOMInfo() +{ +} + +void RetainedDOMInfo::Dispose() +{ + delete this; +} + +bool RetainedDOMInfo::IsEquivalent(v8::RetainedObjectInfo* other) +{ + ASSERT(other); + return other == this || static_cast<WebCore::RetainedObjectInfo*>(other)->GetEquivalenceClass() == this->GetEquivalenceClass(); +} + +intptr_t RetainedDOMInfo::GetHash() +{ + return reinterpret_cast<intptr_t>(m_root); +} + +const char* RetainedDOMInfo::GetLabel() +{ + return m_root->inDocument() ? "Document DOM tree" : "Detached DOM tree"; +} + +intptr_t RetainedDOMInfo::GetElementCount() +{ + intptr_t count = 1; + Node* current = m_root; + while (current) { + current = current->traverseNextNode(m_root); + ++count; + } + return count; +} + +intptr_t RetainedDOMInfo::GetEquivalenceClass() +{ + return reinterpret_cast<intptr_t>(m_root); +} + +} // namespace WebCore diff --git a/Source/WebCore/bindings/v8/RetainedDOMInfo.h b/Source/WebCore/bindings/v8/RetainedDOMInfo.h new file mode 100644 index 0000000..6767f75 --- /dev/null +++ b/Source/WebCore/bindings/v8/RetainedDOMInfo.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2011 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 RetainedDOMInfo_h +#define RetainedDOMInfo_h + +#include "RetainedObjectInfo.h" + +namespace WebCore { + +class Node; + +// Implements v8::RetainedObjectInfo. +class RetainedDOMInfo : public RetainedObjectInfo { +public: + explicit RetainedDOMInfo(Node* root); + virtual ~RetainedDOMInfo(); + virtual void Dispose(); + virtual bool IsEquivalent(v8::RetainedObjectInfo* other); + virtual intptr_t GetHash(); + virtual const char* GetLabel(); + virtual intptr_t GetElementCount(); + virtual intptr_t GetEquivalenceClass(); + +private: + // V8 guarantees to keep RetainedObjectInfos alive only during a GC or heap snapshotting round, when renderer + // doesn't get control. This allows us to use raw pointers. + Node* m_root; +}; + +} // namespace WebCore + +#endif // RetainedDOMInfo_h diff --git a/Source/WebCore/bindings/v8/RetainedObjectInfo.h b/Source/WebCore/bindings/v8/RetainedObjectInfo.h new file mode 100644 index 0000000..0368fb1 --- /dev/null +++ b/Source/WebCore/bindings/v8/RetainedObjectInfo.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2011 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 RetainedObjectInfo_h +#define RetainedObjectInfo_h + +#include <v8-profiler.h> + +namespace WebCore { + +class RetainedObjectInfo : public v8::RetainedObjectInfo { +public: + virtual intptr_t GetEquivalenceClass() = 0; +}; + +} // namespace WebCore + +#endif // RetainedObjectInfo_h diff --git a/Source/WebCore/bindings/v8/ScriptCachedFrameData.cpp b/Source/WebCore/bindings/v8/ScriptCachedFrameData.cpp index dc28f32..9e15d1c 100644 --- a/Source/WebCore/bindings/v8/ScriptCachedFrameData.cpp +++ b/Source/WebCore/bindings/v8/ScriptCachedFrameData.cpp @@ -26,6 +26,10 @@ #include "config.h" #include "ScriptCachedFrameData.h" +#if PLATFORM(ANDROID) || PLATFORM(QT) +// FIXME: the right guard should be ENABLE(PAGE_CACHE). Replace with the right guard, once +// https://bugs.webkit.org/show_bug.cgi?id=35061 is fixed. + #include "Frame.h" #include "ScriptController.h" #include "V8DOMWindow.h" @@ -72,3 +76,5 @@ void ScriptCachedFrameData::clear() } } // namespace WebCore + +#endif // PLATFORM(ANDROID) || PLATFORM(QT) diff --git a/Source/WebCore/bindings/v8/ScriptDebugServer.cpp b/Source/WebCore/bindings/v8/ScriptDebugServer.cpp index cc7fba8..5758639 100644 --- a/Source/WebCore/bindings/v8/ScriptDebugServer.cpp +++ b/Source/WebCore/bindings/v8/ScriptDebugServer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Google Inc. All rights reserved. + * Copyright (c) 2010-2011 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 @@ -33,13 +33,10 @@ #if ENABLE(JAVASCRIPT_DEBUGGER) -#include "Frame.h" +#include "DebuggerScriptSource.h" #include "JavaScriptCallFrame.h" -#include "Page.h" #include "ScriptDebugListener.h" #include "V8Binding.h" -#include "V8DOMWindow.h" -#include "V8Proxy.h" #include <wtf/StdLibExtras.h> namespace WebCore { @@ -57,92 +54,12 @@ private: } -static Frame* retrieveFrame(v8::Handle<v8::Context> context) -{ - if (context.IsEmpty()) - return 0; - - // Test that context has associated global dom window object. - v8::Handle<v8::Object> global = context->Global(); - if (global.IsEmpty()) - return 0; - - global = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), global); - if (global.IsEmpty()) - return 0; - - return V8Proxy::retrieveFrame(context); -} - -ScriptDebugServer& ScriptDebugServer::shared() -{ - DEFINE_STATIC_LOCAL(ScriptDebugServer, server, ()); - return server; -} - ScriptDebugServer::ScriptDebugServer() : m_pauseOnExceptionsState(DontPauseOnExceptions) - , m_pausedPage(0) - , m_enabled(true) , m_breakpointsActivated(true) { } -void ScriptDebugServer::setDebuggerScriptSource(const String& scriptSource) -{ - m_debuggerScriptSource = scriptSource; -} - -void ScriptDebugServer::addListener(ScriptDebugListener* listener, Page* page) -{ - if (!m_enabled) - return; - - V8Proxy* proxy = V8Proxy::retrieve(page->mainFrame()); - if (!proxy) - return; - - v8::HandleScope scope; - v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); - v8::Context::Scope contextScope(debuggerContext); - - if (!m_listenersMap.size()) { - ensureDebuggerScriptCompiled(); - ASSERT(!m_debuggerScript.get()->IsUndefined()); - v8::Debug::SetDebugEventListener2(&ScriptDebugServer::v8DebugEventCallback); - } - m_listenersMap.set(page, listener); - - V8DOMWindowShell* shell = proxy->windowShell(); - if (!shell->isContextInitialized()) - return; - v8::Handle<v8::Context> context = shell->context(); - v8::Handle<v8::Function> getScriptsFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("getScripts"))); - v8::Handle<v8::Value> argv[] = { context->GetData() }; - v8::Handle<v8::Value> value = getScriptsFunction->Call(m_debuggerScript.get(), 1, argv); - if (value.IsEmpty()) - return; - ASSERT(!value->IsUndefined() && value->IsArray()); - v8::Handle<v8::Array> scriptsArray = v8::Handle<v8::Array>::Cast(value); - for (unsigned i = 0; i < scriptsArray->Length(); ++i) - dispatchDidParseSource(listener, v8::Handle<v8::Object>::Cast(scriptsArray->Get(v8::Integer::New(i)))); -} - -void ScriptDebugServer::removeListener(ScriptDebugListener* listener, Page* page) -{ - if (!m_listenersMap.contains(page)) - return; - - if (m_pausedPage == page) - continueProgram(); - - m_listenersMap.remove(page); - - if (m_listenersMap.isEmpty()) - v8::Debug::SetDebugEventListener(0); - // FIXME: Remove all breakpoints set by the agent. -} - String ScriptDebugServer::setBreakpoint(const String& sourceID, const ScriptBreakpoint& scriptBreakpoint, int* actualLineNumber, int* actualColumnNumber) { v8::HandleScope scope; @@ -229,7 +146,7 @@ void ScriptDebugServer::setPauseOnExceptionsState(PauseOnExceptionsState pauseOn void ScriptDebugServer::setPauseOnNextStatement(bool pause) { - if (m_pausedPage) + if (isPaused()) return; if (pause) v8::Debug::DebugBreak(); @@ -239,17 +156,15 @@ void ScriptDebugServer::setPauseOnNextStatement(bool pause) void ScriptDebugServer::breakProgram() { - DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, callbackTemplate, ()); - if (!m_breakpointsActivated) return; if (!v8::Context::InContext()) return; - if (callbackTemplate.IsEmpty()) { - callbackTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New()); - callbackTemplate->SetCallHandler(&ScriptDebugServer::breakProgramCallback); + if (m_breakProgramCallbackTemplate.get().IsEmpty()) { + m_breakProgramCallbackTemplate.set(v8::FunctionTemplate::New()); + m_breakProgramCallbackTemplate.get()->SetCallHandler(&ScriptDebugServer::breakProgramCallback, v8::External::New(this)); } v8::Handle<v8::Context> context = v8::Context::GetCurrent(); @@ -257,21 +172,22 @@ void ScriptDebugServer::breakProgram() return; m_pausedPageContext = *context; - v8::Handle<v8::Function> breakProgramFunction = callbackTemplate->GetFunction(); + v8::Handle<v8::Function> breakProgramFunction = m_breakProgramCallbackTemplate.get()->GetFunction(); v8::Debug::Call(breakProgramFunction); m_pausedPageContext.Clear(); } void ScriptDebugServer::continueProgram() { - if (m_pausedPage) - m_clientMessageLoop->quitNow(); - didResume(); + if (isPaused()) + quitMessageLoopOnPause(); + m_currentCallFrame.clear(); + m_executionState.clear(); } void ScriptDebugServer::stepIntoStatement() { - ASSERT(m_pausedPage); + ASSERT(isPaused()); v8::Handle<v8::Function> function = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("stepIntoStatement"))); v8::Handle<v8::Value> argv[] = { m_executionState.get() }; function->Call(m_debuggerScript.get(), 1, argv); @@ -280,7 +196,7 @@ void ScriptDebugServer::stepIntoStatement() void ScriptDebugServer::stepOverStatement() { - ASSERT(m_pausedPage); + ASSERT(isPaused()); v8::Handle<v8::Function> function = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("stepOverStatement"))); v8::Handle<v8::Value> argv[] = { m_executionState.get() }; function->Call(m_debuggerScript.get(), 1, argv); @@ -289,7 +205,7 @@ void ScriptDebugServer::stepOverStatement() void ScriptDebugServer::stepOutOfFunction() { - ASSERT(m_pausedPage); + ASSERT(isPaused()); v8::Handle<v8::Function> function = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("stepOutOfFunction"))); v8::Handle<v8::Value> argv[] = { m_executionState.get() }; function->Call(m_debuggerScript.get(), 1, argv); @@ -302,7 +218,7 @@ bool ScriptDebugServer::editScriptSource(const String& sourceID, const String& n v8::HandleScope scope; OwnPtr<v8::Context::Scope> contextScope; - if (!m_pausedPage) + if (!isPaused()) contextScope.set(new v8::Context::Scope(v8::Debug::GetDebugContext())); v8::Handle<v8::Function> function = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("editScriptSource"))); @@ -337,11 +253,6 @@ PassRefPtr<JavaScriptCallFrame> ScriptDebugServer::currentCallFrame() return m_currentCallFrame; } -void ScriptDebugServer::setEnabled(bool value) -{ - m_enabled = value; -} - void ScriptDebugServer::interruptAndRun(PassOwnPtr<Task> task) { v8::Debug::DebugBreakForCommand(new ClientDataImpl(task)); @@ -352,44 +263,42 @@ void ScriptDebugServer::runPendingTasks() v8::Debug::ProcessDebugMessages(); } +static ScriptDebugServer* toScriptDebugServer(v8::Handle<v8::Value> data) +{ + void* p = v8::Handle<v8::External>::Cast(data)->Value(); + return static_cast<ScriptDebugServer*>(p); +} + v8::Handle<v8::Value> ScriptDebugServer::breakProgramCallback(const v8::Arguments& args) { ASSERT(2 == args.Length()); - ScriptDebugServer::shared().breakProgram(v8::Handle<v8::Object>::Cast(args[0])); + + ScriptDebugServer* thisPtr = toScriptDebugServer(args.Data()); + thisPtr->breakProgram(v8::Handle<v8::Object>::Cast(args[0])); return v8::Undefined(); } void ScriptDebugServer::breakProgram(v8::Handle<v8::Object> executionState) { // Don't allow nested breaks. - if (m_pausedPage) - return; - - Frame* frame = retrieveFrame(m_pausedPageContext); - if (!frame) + if (isPaused()) return; - ScriptDebugListener* listener = m_listenersMap.get(frame->page()); + ScriptDebugListener* listener = getDebugListenerForContext(m_pausedPageContext); if (!listener) return; m_executionState.set(executionState); - m_pausedPage = frame->page(); ScriptState* currentCallFrameState = ScriptState::forContext(m_pausedPageContext); listener->didPause(currentCallFrameState); - // Wait for continue or step command. - m_clientMessageLoop->run(m_pausedPage); - ASSERT(!m_pausedPage); - - // The listener may have been removed in the nested loop. - if (ScriptDebugListener* listener = m_listenersMap.get(frame->page())) - listener->didContinue(); + runMessageLoopOnPause(m_pausedPageContext); } void ScriptDebugServer::v8DebugEventCallback(const v8::Debug::EventDetails& eventDetails) { - ScriptDebugServer::shared().handleV8DebugEvent(eventDetails); + ScriptDebugServer* thisPtr = toScriptDebugServer(eventDetails.GetCallbackData()); + thisPtr->handleV8DebugEvent(eventDetails); } void ScriptDebugServer::handleV8DebugEvent(const v8::Debug::EventDetails& eventDetails) @@ -408,31 +317,28 @@ void ScriptDebugServer::handleV8DebugEvent(const v8::Debug::EventDetails& eventD v8::Handle<v8::Context> eventContext = eventDetails.GetEventContext(); ASSERT(!eventContext.IsEmpty()); - Frame* frame = retrieveFrame(eventContext); - if (frame) { - ScriptDebugListener* listener = m_listenersMap.get(frame->page()); - if (listener) { - v8::HandleScope scope; - if (event == v8::AfterCompile) { - v8::Context::Scope contextScope(v8::Debug::GetDebugContext()); - v8::Handle<v8::Function> onAfterCompileFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("getAfterCompileScript"))); - v8::Handle<v8::Value> argv[] = { eventDetails.GetEventData() }; - v8::Handle<v8::Value> value = onAfterCompileFunction->Call(m_debuggerScript.get(), 1, argv); - ASSERT(value->IsObject()); - v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); - dispatchDidParseSource(listener, object); - } else if (event == v8::Break || event == v8::Exception) { - if (event == v8::Exception) { - v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(1); - // Stack trace is empty in case of syntax error. Silently continue execution in such cases. - if (!stackTrace->GetFrameCount()) - return; - } - - m_pausedPageContext = *eventContext; - breakProgram(eventDetails.GetExecutionState()); - m_pausedPageContext.Clear(); + ScriptDebugListener* listener = getDebugListenerForContext(eventContext); + if (listener) { + v8::HandleScope scope; + if (event == v8::AfterCompile) { + v8::Context::Scope contextScope(v8::Debug::GetDebugContext()); + v8::Handle<v8::Function> onAfterCompileFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("getAfterCompileScript"))); + v8::Handle<v8::Value> argv[] = { eventDetails.GetEventData() }; + v8::Handle<v8::Value> value = onAfterCompileFunction->Call(m_debuggerScript.get(), 1, argv); + ASSERT(value->IsObject()); + v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); + dispatchDidParseSource(listener, object); + } else if (event == v8::Break || event == v8::Exception) { + if (event == v8::Exception) { + v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(1); + // Stack trace is empty in case of syntax error. Silently continue execution in such cases. + if (!stackTrace->GetFrameCount()) + return; } + + m_pausedPageContext = *eventContext; + breakProgram(eventDetails.GetExecutionState()); + m_pausedPageContext.Clear(); } } } @@ -454,15 +360,14 @@ void ScriptDebugServer::ensureDebuggerScriptCompiled() v8::HandleScope scope; v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); v8::Context::Scope contextScope(debuggerContext); - m_debuggerScript.set(v8::Handle<v8::Object>::Cast(v8::Script::Compile(v8String(m_debuggerScriptSource))->Run())); + String debuggerScriptSource(reinterpret_cast<const char*>(DebuggerScriptSource_js), sizeof(DebuggerScriptSource_js)); + m_debuggerScript.set(v8::Handle<v8::Object>::Cast(v8::Script::Compile(v8String(debuggerScriptSource))->Run())); } } -void ScriptDebugServer::didResume() +bool ScriptDebugServer::isPaused() { - m_currentCallFrame.clear(); - m_executionState.clear(); - m_pausedPage = 0; + return !m_executionState.get().IsEmpty(); } } // namespace WebCore diff --git a/Source/WebCore/bindings/v8/ScriptDebugServer.h b/Source/WebCore/bindings/v8/ScriptDebugServer.h index af3d2ab..15004ea 100644 --- a/Source/WebCore/bindings/v8/ScriptDebugServer.h +++ b/Source/WebCore/bindings/v8/ScriptDebugServer.h @@ -45,17 +45,11 @@ namespace WebCore { -class Page; class ScriptDebugListener; class ScriptDebugServer { WTF_MAKE_NONCOPYABLE(ScriptDebugServer); public: - static ScriptDebugServer& shared(); - - void addListener(ScriptDebugListener*, Page*); - void removeListener(ScriptDebugListener*, Page*); - String setBreakpoint(const String& sourceID, const ScriptBreakpoint&, int* actualLineNumber, int* actualColumnNumber); void removeBreakpoint(const String& breakpointId); void clearBreakpoints(); @@ -83,23 +77,8 @@ public: void recompileAllJSFunctionsSoon() { } void recompileAllJSFunctions(Timer<ScriptDebugServer>* = 0) { } - void pageCreated(Page*) { } - - // v8-specific methods. - void setDebuggerScriptSource(const String& scriptSource); - - class ClientMessageLoop { - public: - virtual ~ClientMessageLoop() { } - virtual void run(Page*) = 0; - virtual void quitNow() = 0; - }; - void setClientMessageLoop(PassOwnPtr<ClientMessageLoop> clientMessageLoop) { m_clientMessageLoop = clientMessageLoop; } - PassRefPtr<JavaScriptCallFrame> currentCallFrame(); - void setEnabled(bool); - class Task { public: virtual ~Task() { } @@ -108,9 +87,13 @@ public: static void interruptAndRun(PassOwnPtr<Task>); void runPendingTasks(); -private: +protected: ScriptDebugServer(); ~ScriptDebugServer() { } + + virtual ScriptDebugListener* getDebugListenerForContext(v8::Handle<v8::Context>) = 0; + virtual void runMessageLoopOnPause(v8::Handle<v8::Context>) = 0; + virtual void quitMessageLoopOnPause() = 0; static v8::Handle<v8::Value> breakProgramCallback(const v8::Arguments& args); void breakProgram(v8::Handle<v8::Object> executionState); @@ -121,21 +104,17 @@ private: void dispatchDidParseSource(ScriptDebugListener* listener, v8::Handle<v8::Object> sourceObject); void ensureDebuggerScriptCompiled(); - void didResume(); + + bool isPaused(); - typedef HashMap<Page*, ScriptDebugListener*> ListenersMap; - ListenersMap m_listenersMap; - String m_debuggerScriptSource; PauseOnExceptionsState m_pauseOnExceptionsState; OwnHandle<v8::Object> m_debuggerScript; RefPtr<JavaScriptCallFrame> m_currentCallFrame; OwnHandle<v8::Object> m_executionState; - OwnPtr<ClientMessageLoop> m_clientMessageLoop; - Page* m_pausedPage; v8::Local<v8::Context> m_pausedPageContext; - bool m_enabled; bool m_breakpointsActivated; + OwnHandle<v8::FunctionTemplate> m_breakProgramCallbackTemplate; }; } // namespace WebCore diff --git a/Source/WebCore/bindings/v8/ScriptHeapSnapshot.cpp b/Source/WebCore/bindings/v8/ScriptHeapSnapshot.cpp index 09e1e54..68ed8da 100644 --- a/Source/WebCore/bindings/v8/ScriptHeapSnapshot.cpp +++ b/Source/WebCore/bindings/v8/ScriptHeapSnapshot.cpp @@ -40,6 +40,11 @@ namespace WebCore { +ScriptHeapSnapshot::~ScriptHeapSnapshot() +{ + const_cast<v8::HeapSnapshot*>(m_snapshot)->Delete(); +} + String ScriptHeapSnapshot::title() const { v8::HandleScope scope; @@ -76,10 +81,4 @@ void ScriptHeapSnapshot::writeJSON(ScriptHeapSnapshot::OutputStream* stream) m_snapshot->Serialize(&outputStream, v8::HeapSnapshot::kJSON); } -int ScriptHeapSnapshot::exactRetainedSize(uint64_t nodeId) -{ - const v8::HeapGraphNode* node = m_snapshot->GetNodeById(nodeId); - return node ? node->GetRetainedSize(true) : -1; -} - } // namespace WebCore diff --git a/Source/WebCore/bindings/v8/ScriptHeapSnapshot.h b/Source/WebCore/bindings/v8/ScriptHeapSnapshot.h index 6cfd76d..4093fa7 100644 --- a/Source/WebCore/bindings/v8/ScriptHeapSnapshot.h +++ b/Source/WebCore/bindings/v8/ScriptHeapSnapshot.h @@ -54,12 +54,11 @@ public: { return adoptRef(new ScriptHeapSnapshot(snapshot)); } - virtual ~ScriptHeapSnapshot() {} + virtual ~ScriptHeapSnapshot(); String title() const; unsigned int uid() const; void writeJSON(OutputStream* stream); - int exactRetainedSize(uint64_t nodeId); private: ScriptHeapSnapshot(const v8::HeapSnapshot* snapshot) diff --git a/Source/WebCore/bindings/v8/ScriptProfile.cpp b/Source/WebCore/bindings/v8/ScriptProfile.cpp index c5a6dbf..2c9f0f5 100644 --- a/Source/WebCore/bindings/v8/ScriptProfile.cpp +++ b/Source/WebCore/bindings/v8/ScriptProfile.cpp @@ -39,6 +39,11 @@ namespace WebCore { +ScriptProfile::~ScriptProfile() +{ + const_cast<v8::CpuProfile*>(m_profile)->Delete(); +} + String ScriptProfile::title() const { v8::HandleScope scope; diff --git a/Source/WebCore/bindings/v8/ScriptProfile.h b/Source/WebCore/bindings/v8/ScriptProfile.h index 0182669..d8196a4 100644 --- a/Source/WebCore/bindings/v8/ScriptProfile.h +++ b/Source/WebCore/bindings/v8/ScriptProfile.h @@ -48,7 +48,7 @@ public: { return adoptRef(new ScriptProfile(profile)); } - virtual ~ScriptProfile() {} + virtual ~ScriptProfile(); String title() const; unsigned int uid() const; diff --git a/Source/WebCore/bindings/v8/ScriptProfiler.cpp b/Source/WebCore/bindings/v8/ScriptProfiler.cpp index 615dcfc..21537f4 100644 --- a/Source/WebCore/bindings/v8/ScriptProfiler.cpp +++ b/Source/WebCore/bindings/v8/ScriptProfiler.cpp @@ -32,12 +32,15 @@ #include "ScriptProfiler.h" #include "InspectorValues.h" +#include "RetainedDOMInfo.h" +#include "V8Binding.h" +#include "V8Node.h" #include <v8-profiler.h> -#include <V8Binding.h> namespace WebCore { +#if ENABLE(INSPECTOR) void ScriptProfiler::start(ScriptState* state, const String& title) { v8::HandleScope hs; @@ -53,6 +56,14 @@ PassRefPtr<ScriptProfile> ScriptProfiler::stop(ScriptState* state, const String& return profile ? ScriptProfile::create(profile) : 0; } +void ScriptProfiler::collectGarbage() +{ + // NOTE : There is currently no direct way to collect memory from the v8 C++ API + // but notifying low-memory forces a mark-compact, which is exactly what we want + // in this case. + v8::V8::LowMemoryNotification(); +} + namespace { class ActivityControlAdapter : public v8::ActivityControl { @@ -90,4 +101,22 @@ PassRefPtr<ScriptHeapSnapshot> ScriptProfiler::takeHeapSnapshot(const String& ti return snapshot ? ScriptHeapSnapshot::create(snapshot) : 0; } +static v8::RetainedObjectInfo* retainedDOMInfo(uint16_t classId, v8::Handle<v8::Value> wrapper) +{ + ASSERT(classId == v8DOMSubtreeClassId); + if (!wrapper->IsObject()) + return 0; + Node* node = V8Node::toNative(wrapper.As<v8::Object>()); + return node ? new RetainedDOMInfo(node) : 0; +} +#endif // ENABLE(INSPECTOR) + +void ScriptProfiler::initialize() +{ +#if ENABLE(INSPECTOR) + v8::HeapProfiler::DefineWrapperClass(v8DOMSubtreeClassId, &retainedDOMInfo); +#endif // ENABLE(INSPECTOR) +} + + } // namespace WebCore diff --git a/Source/WebCore/bindings/v8/ScriptProfiler.h b/Source/WebCore/bindings/v8/ScriptProfiler.h index 9016668..92a980b 100644 --- a/Source/WebCore/bindings/v8/ScriptProfiler.h +++ b/Source/WebCore/bindings/v8/ScriptProfiler.h @@ -53,9 +53,11 @@ public: virtual bool isCanceled() = 0; }; + static void collectGarbage(); static void start(ScriptState* state, const String& title); static PassRefPtr<ScriptProfile> stop(ScriptState* state, const String& title); static PassRefPtr<ScriptHeapSnapshot> takeHeapSnapshot(const String& title, HeapSnapshotProgress*); + static void initialize(); }; } // namespace WebCore diff --git a/Source/WebCore/bindings/v8/SerializedScriptValue.h b/Source/WebCore/bindings/v8/SerializedScriptValue.h index c0e9109..212be66 100644 --- a/Source/WebCore/bindings/v8/SerializedScriptValue.h +++ b/Source/WebCore/bindings/v8/SerializedScriptValue.h @@ -37,7 +37,7 @@ namespace WebCore { -class SerializedScriptValue : public ThreadSafeShared<SerializedScriptValue> { +class SerializedScriptValue : public ThreadSafeRefCounted<SerializedScriptValue> { public: static void deserializeAndSetProperty(v8::Handle<v8::Object>, const char* propertyName, v8::PropertyAttribute, SerializedScriptValue*); diff --git a/Source/WebCore/bindings/v8/V8DOMWindowShell.cpp b/Source/WebCore/bindings/v8/V8DOMWindowShell.cpp index d88d8a6..e025008 100644 --- a/Source/WebCore/bindings/v8/V8DOMWindowShell.cpp +++ b/Source/WebCore/bindings/v8/V8DOMWindowShell.cpp @@ -43,6 +43,7 @@ #include "ScriptCallStack.h" #include "ScriptCallStackFactory.h" #include "ScriptController.h" +#include "ScriptProfiler.h" #include "StorageNamespace.h" #include "V8Binding.h" #include "V8BindingState.h" @@ -305,6 +306,8 @@ bool V8DOMWindowShell::initContextIfNeeded() v8::V8::SetFailedAccessCheckCallbackFunction(reportUnsafeJavaScriptAccess); + ScriptProfiler::initialize(); + isV8Initialized = true; } diff --git a/Source/WebCore/bindings/v8/V8GCController.cpp b/Source/WebCore/bindings/v8/V8GCController.cpp index cda9f3d..82c9ca4 100644 --- a/Source/WebCore/bindings/v8/V8GCController.cpp +++ b/Source/WebCore/bindings/v8/V8GCController.cpp @@ -34,27 +34,20 @@ #include "ActiveDOMObject.h" #include "Attr.h" #include "DOMDataStore.h" -#include "Frame.h" +#include "DOMImplementation.h" #include "HTMLImageElement.h" #include "HTMLNames.h" #include "MessagePort.h" #include "PlatformBridge.h" -#include "SVGElement.h" +#include "RetainedDOMInfo.h" +#include "RetainedObjectInfo.h" #include "V8Binding.h" -#include "V8CSSCharsetRule.h" -#include "V8CSSFontFaceRule.h" -#include "V8CSSImportRule.h" -#include "V8CSSMediaRule.h" +#include "V8CSSRule.h" #include "V8CSSRuleList.h" #include "V8CSSStyleDeclaration.h" -#include "V8CSSStyleRule.h" -#include "V8CSSStyleSheet.h" -#include "V8DOMMap.h" -#include "V8HTMLLinkElement.h" -#include "V8HTMLStyleElement.h" +#include "V8DOMImplementation.h" #include "V8MessagePort.h" -#include "V8ProcessingInstruction.h" -#include "V8Proxy.h" +#include "V8StyleSheet.h" #include "V8StyleSheetList.h" #include "WrapperTypeInfo.h" @@ -175,19 +168,86 @@ public: } }; -class GrouperItem { +// Implements v8::RetainedObjectInfo. +class UnspecifiedGroup : public RetainedObjectInfo { public: - GrouperItem(uintptr_t groupId, v8::Persistent<v8::Object> wrapper) - : m_groupId(groupId) - , m_wrapper(wrapper) - { - } + explicit UnspecifiedGroup(void* object) + : m_object(object) + { + ASSERT(m_object); + } + + virtual void Dispose() { delete this; } + + virtual bool IsEquivalent(v8::RetainedObjectInfo* other) + { + ASSERT(other); + return other == this || static_cast<WebCore::RetainedObjectInfo*>(other)->GetEquivalenceClass() == this->GetEquivalenceClass(); + } + virtual intptr_t GetHash() + { + return reinterpret_cast<intptr_t>(m_object); + } + + virtual const char* GetLabel() + { + return "Object group"; + } + + virtual intptr_t GetEquivalenceClass() + { + return reinterpret_cast<intptr_t>(m_object); + } + +private: + void* m_object; +}; + +class GroupId { +public: + GroupId() : m_type(NullType), m_groupId(0) {} + GroupId(Node* node) : m_type(NodeType), m_node(node) {} + GroupId(void* other) : m_type(OtherType), m_other(other) {} + bool operator!() const { return m_type == NullType; } uintptr_t groupId() const { return m_groupId; } + RetainedObjectInfo* createRetainedObjectInfo() const + { + switch (m_type) { + case NullType: + return 0; + case NodeType: + return new RetainedDOMInfo(m_node); + case OtherType: + return new UnspecifiedGroup(m_other); + default: + return 0; + } + } + +private: + enum Type { + NullType, + NodeType, + OtherType + }; + Type m_type; + union { + uintptr_t m_groupId; + Node* m_node; + void* m_other; + }; +}; + +class GrouperItem { +public: + GrouperItem(GroupId groupId, v8::Persistent<v8::Object> wrapper) : m_groupId(groupId), m_wrapper(wrapper) {} + uintptr_t groupId() const { return m_groupId.groupId(); } + RetainedObjectInfo* createRetainedObjectInfo() const { return m_groupId.createRetainedObjectInfo(); } v8::Persistent<v8::Object> wrapper() const { return m_wrapper; } private: - uintptr_t m_groupId; + GroupId m_groupId; v8::Persistent<v8::Object> m_wrapper; }; @@ -198,215 +258,160 @@ bool operator<(const GrouperItem& a, const GrouperItem& b) typedef Vector<GrouperItem> GrouperList; -void makeV8ObjectGroups(GrouperList& grouper) +// If the node is in document, put it in the ownerDocument's object group. +// +// If an image element was created by JavaScript "new Image", +// it is not in a document. However, if the load event has not +// been fired (still onloading), it is treated as in the document. +// +// Otherwise, the node is put in an object group identified by the root +// element of the tree to which it belongs. +static GroupId calculateGroupId(Node* node) { - // Group by sorting by the group id. - std::sort(grouper.begin(), grouper.end()); - - // FIXME Should probably work in iterators here, but indexes were easier for my simple mind. - for (size_t i = 0; i < grouper.size(); ) { - // Seek to the next key (or the end of the list). - size_t nextKeyIndex = grouper.size(); - for (size_t j = i; j < grouper.size(); ++j) { - if (grouper[i].groupId() != grouper[j].groupId()) { - nextKeyIndex = j; - break; - } - } + if (node->inDocument() || (node->hasTagName(HTMLNames::imgTag) && !static_cast<HTMLImageElement*>(node)->haveFiredLoadEvent())) + return GroupId(node->document()); + + Node* root = node; + if (node->isAttributeNode()) { + root = static_cast<Attr*>(node)->ownerElement(); + // If the attribute has no element, no need to put it in the group, + // because it'll always be a group of 1. + if (!root) + return GroupId(); + } else { + while (Node* parent = root->parentNode()) + root = parent; + } - ASSERT(nextKeyIndex > i); + return GroupId(root); +} - // We only care about a group if it has more than one object. If it only - // has one object, it has nothing else that needs to be kept alive. - if (nextKeyIndex - i <= 1) { - i = nextKeyIndex; - continue; +static GroupId calculateGroupId(StyleBase* styleBase) +{ + ASSERT(styleBase); + StyleBase* current = styleBase; + StyleSheet* styleSheet = 0; + while (true) { + // Special case: CSSStyleDeclarations might be either inline and in this case + // we need to group them with their node or regular ones. + if (current->isMutableStyleDeclaration()) { + CSSMutableStyleDeclaration* cssMutableStyleDeclaration = static_cast<CSSMutableStyleDeclaration*>(current); + if (cssMutableStyleDeclaration->isInlineStyleDeclaration()) { + ASSERT(cssMutableStyleDeclaration->parent()->isStyleSheet()); + return calculateGroupId(cssMutableStyleDeclaration->node()); + } + // Either we have no parent, or this parent is a CSSRule. + ASSERT(cssMutableStyleDeclaration->parent() == cssMutableStyleDeclaration->parentRule()); } - Vector<v8::Persistent<v8::Value> > group; - group.reserveCapacity(nextKeyIndex - i); - for (; i < nextKeyIndex; ++i) { - v8::Persistent<v8::Value> wrapper = grouper[i].wrapper(); - if (!wrapper.IsEmpty()) - group.append(wrapper); - } + if (current->isStyleSheet()) + styleSheet = static_cast<StyleSheet*>(current); - if (group.size() > 1) - v8::V8::AddObjectGroup(&group[0], group.size()); + StyleBase* parent = current->parent(); + if (!parent) + break; + current = parent; + } - ASSERT(i == nextKeyIndex); + if (styleSheet) { + if (Node* ownerNode = styleSheet->ownerNode()) + return calculateGroupId(ownerNode); + return GroupId(styleSheet); } + + return GroupId(current); } -class NodeGrouperVisitor : public DOMWrapperMap<Node>::Visitor { +class GrouperVisitor : public DOMWrapperMap<Node>::Visitor, public DOMWrapperMap<void>::Visitor { public: - NodeGrouperVisitor() - { - // FIXME: grouper_.reserveCapacity(node_map.size()); ? - } - void visitDOMWrapper(DOMDataStore* store, Node* node, v8::Persistent<v8::Object> wrapper) { - // If the node is in document, put it in the ownerDocument's object group. - // - // If an image element was created by JavaScript "new Image", - // it is not in a document. However, if the load event has not - // been fired (still onloading), it is treated as in the document. - // - // Otherwise, the node is put in an object group identified by the root - // element of the tree to which it belongs. - uintptr_t groupId; - if (node->inDocument() || (node->hasTagName(HTMLNames::imgTag) && !static_cast<HTMLImageElement*>(node)->haveFiredLoadEvent())) - groupId = reinterpret_cast<uintptr_t>(node->document()); - else { - Node* root = node; - if (node->isAttributeNode()) { - root = static_cast<Attr*>(node)->ownerElement(); - // If the attribute has no element, no need to put it in the group, - // because it'll always be a group of 1. - if (!root) - return; - } else { - while (root->parentNode()) - root = root->parentNode(); - - // If the node is alone in its DOM tree (doesn't have a parent or any - // children) then the group will be filtered out later anyway. - if (root == node && !node->hasChildNodes() && !node->hasAttributes()) - return; - } - groupId = reinterpret_cast<uintptr_t>(root); - } + GroupId groupId = calculateGroupId(node); + if (!groupId) + return; m_grouper.append(GrouperItem(groupId, 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); - addDOMObjectToGroup(store, groupId, element->inlineStyleDecl()); - } - - if (node->isDocumentNode()) { - Document* document = reinterpret_cast<Document*>(node); - addDOMObjectToGroup(store, groupId, document->styleSheets()); - addDOMObjectToGroup(store, groupId, document->implementation()); - } - + void visitDOMWrapper(DOMDataStore* store, void* object, v8::Persistent<v8::Object> wrapper) + { WrapperTypeInfo* typeInfo = V8DOMWrapper::domWrapperType(wrapper); - if (V8HTMLLinkElement::info.equals(typeInfo)) { - HTMLLinkElement* htmlLinkElement = static_cast<HTMLLinkElement*>(node); - addDOMObjectToGroup(store, groupId, htmlLinkElement->sheet()); - } + if (typeInfo->isSubclass(&V8StyleSheetList::info)) { + StyleSheetList* styleSheetList = static_cast<StyleSheetList*>(object); + GroupId groupId(styleSheetList); + if (Document* document = styleSheetList->document()) + groupId = GroupId(document); + m_grouper.append(GrouperItem(groupId, wrapper)); - if (V8HTMLStyleElement::info.equals(typeInfo)) { - HTMLStyleElement* htmlStyleElement = static_cast<HTMLStyleElement*>(node); - addDOMObjectToGroup(store, groupId, htmlStyleElement->sheet()); - } + } else if (typeInfo->isSubclass(&V8DOMImplementation::info)) { + DOMImplementation* domImplementation = static_cast<DOMImplementation*>(object); + GroupId groupId(domImplementation); + if (Document* document = domImplementation->ownerDocument()) + groupId = GroupId(document); + m_grouper.append(GrouperItem(groupId, wrapper)); - if (V8ProcessingInstruction::info.equals(typeInfo)) { - ProcessingInstruction* processingInstruction = static_cast<ProcessingInstruction*>(node); - addDOMObjectToGroup(store, groupId, processingInstruction->sheet()); - } - } + } else if (typeInfo->isSubclass(&V8StyleSheet::info) || typeInfo->isSubclass(&V8CSSRule::info)) { + m_grouper.append(GrouperItem(calculateGroupId(static_cast<StyleBase*>(object)), wrapper)); - void applyGrouping() - { - makeV8ObjectGroups(m_grouper); - } - -private: - GrouperList m_grouper; + } else if (typeInfo->isSubclass(&V8CSSStyleDeclaration::info)) { + CSSStyleDeclaration* cssStyleDeclaration = static_cast<CSSStyleDeclaration*>(object); - void addDOMObjectToGroup(DOMDataStore* store, uintptr_t groupId, void* object) - { - if (!object) - return; - v8::Persistent<v8::Object> wrapper = store->domObjectMap().get(object); - if (!wrapper.IsEmpty()) + GroupId groupId = calculateGroupId(cssStyleDeclaration); m_grouper.append(GrouperItem(groupId, wrapper)); - } -}; -class DOMObjectGrouperVisitor : public DOMWrapperMap<void>::Visitor { -public: - DOMObjectGrouperVisitor() - { + } else if (typeInfo->isSubclass(&V8CSSRuleList::info)) { + CSSRuleList* cssRuleList = static_cast<CSSRuleList*>(object); + GroupId groupId(cssRuleList); + StyleList* styleList = cssRuleList->styleList(); + if (styleList) + groupId = calculateGroupId(styleList); + m_grouper.append(GrouperItem(groupId, wrapper)); + } } - void startMap() + void applyGrouping() { - m_grouper.shrink(0); - } + // Group by sorting by the group id. + std::sort(m_grouper.begin(), m_grouper.end()); + + for (size_t i = 0; i < m_grouper.size(); ) { + // Seek to the next key (or the end of the list). + size_t nextKeyIndex = m_grouper.size(); + for (size_t j = i; j < m_grouper.size(); ++j) { + if (m_grouper[i].groupId() != m_grouper[j].groupId()) { + nextKeyIndex = j; + break; + } + } - void endMap() - { - makeV8ObjectGroups(m_grouper); - } + ASSERT(nextKeyIndex > i); - void visitDOMWrapper(DOMDataStore* store, void* object, v8::Persistent<v8::Object> wrapper) - { - WrapperTypeInfo* typeInfo = V8DOMWrapper::domWrapperType(wrapper); - // FIXME: extend WrapperTypeInfo with isStyle to simplify the check below or consider - // adding a virtual method to WrapperTypeInfo which would know how to group objects. - // FIXME: check if there are other StyleBase wrappers we should care of. - if (V8CSSStyleSheet::info.equals(typeInfo) - || V8CSSStyleDeclaration::info.equals(typeInfo) - || V8CSSCharsetRule::info.equals(typeInfo) - || V8CSSFontFaceRule::info.equals(typeInfo) - || V8CSSStyleRule::info.equals(typeInfo) - || V8CSSImportRule::info.equals(typeInfo) - || V8CSSMediaRule::info.equals(typeInfo)) { - StyleBase* styleBase = static_cast<StyleBase*>(object); - - // We put the whole tree of style elements into a single object group. - // To achieve that we group elements by the roots of their trees. - StyleBase* root = styleBase; - ASSERT(root); - while (true) { - StyleBase* parent = root->parent(); - if (!parent) - break; - root = parent; + // We only care about a group if it has more than one object. If it only + // has one object, it has nothing else that needs to be kept alive. + if (nextKeyIndex - i <= 1) { + i = nextKeyIndex; + continue; } - // Group id is an address of the root. - uintptr_t groupId = reinterpret_cast<uintptr_t>(root); - m_grouper.append(GrouperItem(groupId, wrapper)); - if (V8CSSStyleDeclaration::info.equals(typeInfo)) { - CSSStyleDeclaration* cssStyleDeclaration = static_cast<CSSStyleDeclaration*>(styleBase); - if (cssStyleDeclaration->isMutableStyleDeclaration()) { - CSSMutableStyleDeclaration* cssMutableStyleDeclaration = static_cast<CSSMutableStyleDeclaration*>(cssStyleDeclaration); - CSSMutableStyleDeclaration::const_iterator end = cssMutableStyleDeclaration->end(); - for (CSSMutableStyleDeclaration::const_iterator it = cssMutableStyleDeclaration->begin(); it != end; ++it) { - wrapper = store->domObjectMap().get(it->value()); - if (!wrapper.IsEmpty()) - m_grouper.append(GrouperItem(groupId, wrapper)); - } - } + size_t rootIndex = i; + + Vector<v8::Persistent<v8::Value> > group; + group.reserveCapacity(nextKeyIndex - i); + for (; i < nextKeyIndex; ++i) { + v8::Persistent<v8::Value> wrapper = m_grouper[i].wrapper(); + if (!wrapper.IsEmpty()) + group.append(wrapper); } - } else if (V8StyleSheetList::info.equals(typeInfo)) { - addAllItems(store, static_cast<StyleSheetList*>(object), wrapper); - } else if (V8CSSRuleList::info.equals(typeInfo)) { - addAllItems(store, static_cast<CSSRuleList*>(object), wrapper); + + if (group.size() > 1) + v8::V8::AddObjectGroup(&group[0], group.size(), m_grouper[rootIndex].createRetainedObjectInfo()); + + ASSERT(i == nextKeyIndex); } } private: GrouperList m_grouper; - - template <class C> - void addAllItems(DOMDataStore* store, C* collection, v8::Persistent<v8::Object> wrapper) - { - uintptr_t groupId = reinterpret_cast<uintptr_t>(collection); - m_grouper.append(GrouperItem(groupId, wrapper)); - for (unsigned i = 0; i < collection->length(); i++) { - wrapper = store->domObjectMap().get(collection->item(i)); - if (!wrapper.IsEmpty()) - m_grouper.append(GrouperItem(groupId, wrapper)); - } - } }; // Create object groups for DOM tree nodes. @@ -425,12 +430,10 @@ void V8GCController::gcPrologue() visitActiveDOMObjectsInCurrentThread(&prologueVisitor); // Create object groups. - NodeGrouperVisitor nodeGrouperVisitor; - visitDOMNodesInCurrentThread(&nodeGrouperVisitor); - nodeGrouperVisitor.applyGrouping(); - - DOMObjectGrouperVisitor domObjectGrouperVisitor; - visitDOMObjectsInCurrentThread(&domObjectGrouperVisitor); + GrouperVisitor grouperVisitor; + visitDOMNodesInCurrentThread(&grouperVisitor); + visitDOMObjectsInCurrentThread(&grouperVisitor); + grouperVisitor.applyGrouping(); // Clean single element cache for string conversions. lastStringImpl = 0; diff --git a/Source/WebCore/bindings/v8/V8LazyEventListener.cpp b/Source/WebCore/bindings/v8/V8LazyEventListener.cpp index 7f46333..0e2c368 100644 --- a/Source/WebCore/bindings/v8/V8LazyEventListener.cpp +++ b/Source/WebCore/bindings/v8/V8LazyEventListener.cpp @@ -31,6 +31,7 @@ #include "config.h" #include "V8LazyEventListener.h" +#include "ContentSecurityPolicy.h" #include "Frame.h" #include "V8Binding.h" #include "V8HiddenPropertyName.h" @@ -80,6 +81,9 @@ void V8LazyEventListener::prepareListenerObject(ScriptExecutionContext* context) if (hasExistingListenerObject()) return; + if (context->isDocument() && !static_cast<Document*>(context)->contentSecurityPolicy()->allowInlineEventHandlers()) + return; + v8::HandleScope handleScope; V8Proxy* proxy = V8Proxy::retrieve(context); diff --git a/Source/WebCore/bindings/v8/WorkerScriptDebugServer.cpp b/Source/WebCore/bindings/v8/WorkerScriptDebugServer.cpp new file mode 100755 index 0000000..5e2acd2 --- /dev/null +++ b/Source/WebCore/bindings/v8/WorkerScriptDebugServer.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2011 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 "WorkerScriptDebugServer.h" + +#if ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(WORKERS) + +#include "WorkerContext.h" + +namespace WebCore { + +WorkerScriptDebugServer::WorkerScriptDebugServer() + : ScriptDebugServer() +{ +} + +void WorkerScriptDebugServer::addListener(ScriptDebugListener*, WorkerContext*) +{ +} + +void WorkerScriptDebugServer::removeListener(ScriptDebugListener*, WorkerContext*) +{ +} + +} // namespace WebCore + +#endif // ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(WORKERS) diff --git a/Source/WebCore/bindings/v8/WorkerScriptDebugServer.h b/Source/WebCore/bindings/v8/WorkerScriptDebugServer.h new file mode 100755 index 0000000..fdc47ac --- /dev/null +++ b/Source/WebCore/bindings/v8/WorkerScriptDebugServer.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2011 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 WorkerScriptDebugServer_h +#define WorkerScriptDebugServer_h + +#if ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(WORKERS) + +#include "ScriptDebugServer.h" + +namespace WebCore { + +class WorkerContext; + +class WorkerScriptDebugServer : public ScriptDebugServer { + WTF_MAKE_NONCOPYABLE(WorkerScriptDebugServer); +public: + WorkerScriptDebugServer(); + ~WorkerScriptDebugServer() { } + + void addListener(ScriptDebugListener*, WorkerContext*); + void removeListener(ScriptDebugListener*, WorkerContext*); + +private: + virtual ScriptDebugListener* getDebugListenerForContext(v8::Handle<v8::Context>) { return 0; } + virtual void runMessageLoopOnPause(v8::Handle<v8::Context>) { } + virtual void quitMessageLoopOnPause() { } +}; + +} // namespace WebCore + +#endif // ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(WORKERS) + +#endif // WorkerScriptDebugServer_h diff --git a/Source/WebCore/bindings/v8/WrapperTypeInfo.h b/Source/WebCore/bindings/v8/WrapperTypeInfo.h index 1d1cbfd..166d642 100644 --- a/Source/WebCore/bindings/v8/WrapperTypeInfo.h +++ b/Source/WebCore/bindings/v8/WrapperTypeInfo.h @@ -41,7 +41,9 @@ namespace WebCore { static const int v8DOMWrapperObjectIndex = 1; static const int v8DOMHiddenReferenceArrayIndex = 2; static const int v8DefaultWrapperInternalFieldCount = 3; - + + static const uint16_t v8DOMSubtreeClassId = 1; + typedef v8::Persistent<v8::FunctionTemplate> (*GetTemplateFunction)(); typedef void (*DerefObjectFunction)(void*); typedef ActiveDOMObject* (*ToActiveDOMObjectFunction)(v8::Handle<v8::Object>); @@ -61,6 +63,16 @@ namespace WebCore { { return this == that; } + + bool isSubclass(const WrapperTypeInfo* that) const + { + for (const WrapperTypeInfo* current = this; current; current = current->parentClass) { + if (current == that) + return true; + } + + return false; + } v8::Persistent<v8::FunctionTemplate> getTemplate() { return getTemplateFunction(); } @@ -80,6 +92,7 @@ namespace WebCore { const GetTemplateFunction getTemplateFunction; const DerefObjectFunction derefObjectFunction; const ToActiveDOMObjectFunction toActiveDOMObjectFunction; + const WrapperTypeInfo* parentClass; }; } diff --git a/Source/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp b/Source/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp index 8fd2d62..52465b6 100644 --- a/Source/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp +++ b/Source/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp @@ -76,6 +76,9 @@ v8::Handle<v8::Value> V8HTMLCanvasElement::getContextCallback(const v8::Argument v8::Handle<v8::String> premultipliedAlpha = v8::String::New("premultipliedAlpha"); if (jsAttrs->Has(premultipliedAlpha)) webGLAttrs->setPremultipliedAlpha(jsAttrs->Get(premultipliedAlpha)->BooleanValue()); + v8::Handle<v8::String> preserveDrawingBuffer = v8::String::New("preserveDrawingBuffer"); + if (jsAttrs->Has(preserveDrawingBuffer)) + webGLAttrs->setPreserveDrawingBuffer(jsAttrs->Get(preserveDrawingBuffer)->BooleanValue()); } } #endif diff --git a/Source/WebCore/bindings/v8/custom/V8IDBAnyCustom.cpp b/Source/WebCore/bindings/v8/custom/V8IDBAnyCustom.cpp index ccd6fb2..a1a8636 100644 --- a/Source/WebCore/bindings/v8/custom/V8IDBAnyCustom.cpp +++ b/Source/WebCore/bindings/v8/custom/V8IDBAnyCustom.cpp @@ -77,6 +77,6 @@ v8::Handle<v8::Value> toV8(IDBAny* impl) return v8::Undefined(); } -#endif // ENABLE(INDEXED_DATABASE) - } // namespace WebCore + +#endif // ENABLE(INDEXED_DATABASE) diff --git a/Source/WebCore/bindings/v8/custom/V8IDBKeyCustom.cpp b/Source/WebCore/bindings/v8/custom/V8IDBKeyCustom.cpp index 3805dca..b8fa6bb 100644 --- a/Source/WebCore/bindings/v8/custom/V8IDBKeyCustom.cpp +++ b/Source/WebCore/bindings/v8/custom/V8IDBKeyCustom.cpp @@ -56,6 +56,6 @@ v8::Handle<v8::Value> toV8(IDBKey* key) return v8::Undefined(); } -#endif // ENABLE(INDEXED_DATABASE) - } // namespace WebCore + +#endif // ENABLE(INDEXED_DATABASE) diff --git a/Source/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp b/Source/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp index 7a33ed0..3dbacb2 100644 --- a/Source/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp +++ b/Source/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007-2009 Google Inc. All rights reserved. + * Copyright (C) 2007-2011 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 @@ -31,27 +31,21 @@ #include "config.h" #include "V8InjectedScriptHost.h" -#include "DOMWindow.h" #include "Database.h" -#include "Frame.h" #include "InjectedScript.h" #include "InjectedScriptHost.h" +#include "InspectorDebuggerAgent.h" #include "InspectorValues.h" -#include "Node.h" -#include "Page.h" #include "ScriptDebugServer.h" #include "ScriptValue.h" - #include "V8Binding.h" #include "V8BindingState.h" -#include "V8DOMWindow.h" #include "V8Database.h" #include "V8HiddenPropertyName.h" #include "V8JavaScriptCallFrame.h" #include "V8Node.h" #include "V8Proxy.h" #include "V8Storage.h" -#include <wtf/RefPtr.h> namespace WebCore { @@ -71,86 +65,6 @@ ScriptValue InjectedScriptHost::nodeAsScriptValue(ScriptState* state, Node* node return ScriptValue(toV8(node)); } -static void WeakReferenceCallback(v8::Persistent<v8::Value> object, void* parameter) -{ - InjectedScriptHost* nativeObject = static_cast<InjectedScriptHost*>(parameter); - nativeObject->deref(); - object.Dispose(); -} - -static v8::Local<v8::Object> createInjectedScriptHostV8Wrapper(InjectedScriptHost* host) -{ - v8::Local<v8::Function> function = V8InjectedScriptHost::GetTemplate()->GetFunction(); - if (function.IsEmpty()) { - // Return if allocation failed. - return v8::Local<v8::Object>(); - } - v8::Local<v8::Object> instance = SafeAllocation::newInstance(function); - if (instance.IsEmpty()) { - // Avoid setting the wrapper if allocation failed. - return v8::Local<v8::Object>(); - } - V8DOMWrapper::setDOMWrapper(instance, &V8InjectedScriptHost::info, host); - // Create a weak reference to the v8 wrapper of InspectorBackend to deref - // InspectorBackend when the wrapper is garbage collected. - host->ref(); - v8::Persistent<v8::Object> weakHandle = v8::Persistent<v8::Object>::New(instance); - weakHandle.MakeWeak(host, &WeakReferenceCallback); - return instance; -} - -ScriptObject InjectedScriptHost::createInjectedScript(const String& scriptSource, ScriptState* inspectedScriptState, long id) -{ - v8::HandleScope scope; - - v8::Local<v8::Context> inspectedContext = inspectedScriptState->context(); - v8::Context::Scope contextScope(inspectedContext); - - // Call custom code to create InjectedScripHost wrapper specific for the context - // instead of calling toV8() that would create the - // wrapper in the current context. - // FIXME: make it possible to use generic bindings factory for InjectedScriptHost. - v8::Local<v8::Object> scriptHostWrapper = createInjectedScriptHostV8Wrapper(this); - if (scriptHostWrapper.IsEmpty()) - return ScriptObject(); - - v8::Local<v8::Object> windowGlobal = inspectedContext->Global(); - - // Inject javascript into the context. The compiled script is supposed to evaluate into - // a single anonymous function(it's anonymous to avoid cluttering the global object with - // inspector's stuff) the function is called a few lines below with InjectedScriptHost wrapper, - // injected script id and explicit reference to the inspected global object. The function is expected - // to create and configure InjectedScript instance that is going to be used by the inspector. - v8::Local<v8::Script> script = v8::Script::Compile(v8String(scriptSource)); - v8::Local<v8::Value> v = script->Run(); - ASSERT(!v.IsEmpty()); - ASSERT(v->IsFunction()); - - v8::Handle<v8::Value> args[] = { - scriptHostWrapper, - windowGlobal, - v8::Number::New(id), - }; - v8::Local<v8::Value> injectedScriptValue = v8::Function::Cast(*v)->Call(windowGlobal, 3, args); - v8::Local<v8::Object> injectedScript(v8::Object::Cast(*injectedScriptValue)); - return ScriptObject(inspectedScriptState, injectedScript); -} - -void InjectedScriptHost::discardInjectedScript(ScriptState* inspectedScriptState) -{ - v8::HandleScope handleScope; - v8::Local<v8::Context> context = inspectedScriptState->context(); - v8::Context::Scope contextScope(context); - - v8::Local<v8::Object> global = context->Global(); - // Skip proxy object. The proxy object will survive page navigation while we need - // an object whose lifetime consides with that of the inspected context. - global = v8::Local<v8::Object>::Cast(global->GetPrototype()); - - v8::Handle<v8::String> key = V8HiddenPropertyName::devtoolsInjectedScript(); - global->DeleteHiddenValue(key); -} - v8::Handle<v8::Value> V8InjectedScriptHost::inspectedNodeCallback(const v8::Arguments& args) { INC_STATS("InjectedScriptHost.inspectedNode()"); @@ -185,9 +99,9 @@ v8::Handle<v8::Value> V8InjectedScriptHost::inspectCallback(const v8::Arguments& return v8::Undefined(); InjectedScriptHost* host = V8InjectedScriptHost::toNative(args.Holder()); - ScriptValue objectId(args[0]); + ScriptValue object(args[0]); ScriptValue hints(args[1]); - host->inspectImpl(objectId.toInspectorValue(ScriptState::current()), hints.toInspectorValue(ScriptState::current())); + host->inspectImpl(object.toInspectorValue(ScriptState::current()), hints.toInspectorValue(ScriptState::current())); return v8::Undefined(); } @@ -196,7 +110,8 @@ v8::Handle<v8::Value> V8InjectedScriptHost::currentCallFrameCallback(const v8::A { #if ENABLE(JAVASCRIPT_DEBUGGER) INC_STATS("InjectedScriptHost.currentCallFrame()"); - return toV8(ScriptDebugServer::shared().currentCallFrame()); + InjectedScriptHost* host = V8InjectedScriptHost::toNative(args.Holder()); + return toV8(host->debuggerAgent()->scriptDebugServer().currentCallFrame()); #else UNUSED_PARAM(args); return v8::Undefined(); @@ -231,46 +146,4 @@ v8::Handle<v8::Value> V8InjectedScriptHost::storageIdCallback(const v8::Argument return v8::Undefined(); } -InjectedScript InjectedScriptHost::injectedScriptFor(ScriptState* inspectedScriptState) -{ - v8::HandleScope handleScope; - v8::Local<v8::Context> context = inspectedScriptState->context(); - v8::Context::Scope contextScope(context); - - v8::Local<v8::Object> global = context->Global(); - // Skip proxy object. The proxy object will survive page navigation while we need - // an object whose lifetime consides with that of the inspected context. - global = v8::Local<v8::Object>::Cast(global->GetPrototype()); - - v8::Handle<v8::String> key = V8HiddenPropertyName::devtoolsInjectedScript(); - v8::Local<v8::Value> val = global->GetHiddenValue(key); - if (!val.IsEmpty() && val->IsObject()) - return InjectedScript(ScriptObject(inspectedScriptState, v8::Local<v8::Object>::Cast(val))); - - if (!canAccessInspectedWindow(inspectedScriptState)) - return InjectedScript(); - - pair<long, ScriptObject> injectedScript = injectScript(injectedScriptSource(), inspectedScriptState); - InjectedScript result(injectedScript.second); - m_idToInjectedScript.set(injectedScript.first, result); - global->SetHiddenValue(key, injectedScript.second.v8Object()); - return result; -} - -bool InjectedScriptHost::canAccessInspectedWindow(ScriptState* scriptState) -{ - v8::HandleScope handleScope; - v8::Local<v8::Context> context = scriptState->context(); - v8::Local<v8::Object> global = context->Global(); - if (global.IsEmpty()) - return false; - v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), global); - if (holder.IsEmpty()) - return false; - Frame* frame = V8DOMWindow::toNative(holder)->frame(); - - v8::Context::Scope contextScope(context); - return V8BindingSecurity::canAccessFrame(V8BindingState::Only(), frame, false); -} - } // namespace WebCore diff --git a/Source/WebCore/bindings/v8/custom/V8InjectedScriptManager.cpp b/Source/WebCore/bindings/v8/custom/V8InjectedScriptManager.cpp new file mode 100644 index 0000000..f4006b8 --- /dev/null +++ b/Source/WebCore/bindings/v8/custom/V8InjectedScriptManager.cpp @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2007-2011 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 "InjectedScriptManager.h" + +#include "DOMWindow.h" +#include "InjectedScript.h" +#include "InjectedScriptHost.h" +#include "ScriptValue.h" +#include "V8Binding.h" +#include "V8BindingState.h" +#include "V8DOMWindow.h" +#include "V8HiddenPropertyName.h" +#include "V8InjectedScriptHost.h" +#include "V8Proxy.h" +#include <wtf/RefPtr.h> + +namespace WebCore { + +static void WeakReferenceCallback(v8::Persistent<v8::Value> object, void* parameter) +{ + InjectedScriptHost* nativeObject = static_cast<InjectedScriptHost*>(parameter); + nativeObject->deref(); + object.Dispose(); +} + +static v8::Local<v8::Object> createInjectedScriptHostV8Wrapper(InjectedScriptHost* host) +{ + v8::Local<v8::Function> function = V8InjectedScriptHost::GetTemplate()->GetFunction(); + if (function.IsEmpty()) { + // Return if allocation failed. + return v8::Local<v8::Object>(); + } + v8::Local<v8::Object> instance = SafeAllocation::newInstance(function); + if (instance.IsEmpty()) { + // Avoid setting the wrapper if allocation failed. + return v8::Local<v8::Object>(); + } + V8DOMWrapper::setDOMWrapper(instance, &V8InjectedScriptHost::info, host); + // Create a weak reference to the v8 wrapper of InspectorBackend to deref + // InspectorBackend when the wrapper is garbage collected. + host->ref(); + v8::Persistent<v8::Object> weakHandle = v8::Persistent<v8::Object>::New(instance); + weakHandle.MakeWeak(host, &WeakReferenceCallback); + return instance; +} + +ScriptObject InjectedScriptManager::createInjectedScript(const String& scriptSource, ScriptState* inspectedScriptState, long id) +{ + v8::HandleScope scope; + + v8::Local<v8::Context> inspectedContext = inspectedScriptState->context(); + v8::Context::Scope contextScope(inspectedContext); + + // Call custom code to create InjectedScripHost wrapper specific for the context + // instead of calling toV8() that would create the + // wrapper in the current context. + // FIXME: make it possible to use generic bindings factory for InjectedScriptHost. + v8::Local<v8::Object> scriptHostWrapper = createInjectedScriptHostV8Wrapper(m_injectedScriptHost.get()); + if (scriptHostWrapper.IsEmpty()) + return ScriptObject(); + + v8::Local<v8::Object> windowGlobal = inspectedContext->Global(); + + // Inject javascript into the context. The compiled script is supposed to evaluate into + // a single anonymous function(it's anonymous to avoid cluttering the global object with + // inspector's stuff) the function is called a few lines below with InjectedScriptHost wrapper, + // injected script id and explicit reference to the inspected global object. The function is expected + // to create and configure InjectedScript instance that is going to be used by the inspector. + v8::Local<v8::Script> script = v8::Script::Compile(v8String(scriptSource)); + v8::Local<v8::Value> v = script->Run(); + ASSERT(!v.IsEmpty()); + ASSERT(v->IsFunction()); + + v8::Handle<v8::Value> args[] = { + scriptHostWrapper, + windowGlobal, + v8::Number::New(id), + }; + v8::Local<v8::Value> injectedScriptValue = v8::Function::Cast(*v)->Call(windowGlobal, 3, args); + v8::Local<v8::Object> injectedScript(v8::Object::Cast(*injectedScriptValue)); + return ScriptObject(inspectedScriptState, injectedScript); +} + +void InjectedScriptManager::discardInjectedScript(ScriptState* inspectedScriptState) +{ + v8::HandleScope handleScope; + v8::Local<v8::Context> context = inspectedScriptState->context(); + v8::Context::Scope contextScope(context); + + v8::Local<v8::Object> global = context->Global(); + // Skip proxy object. The proxy object will survive page navigation while we need + // an object whose lifetime consides with that of the inspected context. + global = v8::Local<v8::Object>::Cast(global->GetPrototype()); + + v8::Handle<v8::String> key = V8HiddenPropertyName::devtoolsInjectedScript(); + global->DeleteHiddenValue(key); +} + +InjectedScript InjectedScriptManager::injectedScriptFor(ScriptState* inspectedScriptState) +{ + v8::HandleScope handleScope; + v8::Local<v8::Context> context = inspectedScriptState->context(); + v8::Context::Scope contextScope(context); + + v8::Local<v8::Object> global = context->Global(); + // Skip proxy object. The proxy object will survive page navigation while we need + // an object whose lifetime consides with that of the inspected context. + global = v8::Local<v8::Object>::Cast(global->GetPrototype()); + + v8::Handle<v8::String> key = V8HiddenPropertyName::devtoolsInjectedScript(); + v8::Local<v8::Value> val = global->GetHiddenValue(key); + if (!val.IsEmpty() && val->IsObject()) + return InjectedScript(ScriptObject(inspectedScriptState, v8::Local<v8::Object>::Cast(val))); + + if (!canAccessInspectedWindow(inspectedScriptState)) + return InjectedScript(); + + pair<long, ScriptObject> injectedScript = injectScript(injectedScriptSource(), inspectedScriptState); + InjectedScript result(injectedScript.second); + m_idToInjectedScript.set(injectedScript.first, result); + global->SetHiddenValue(key, injectedScript.second.v8Object()); + return result; +} + +bool InjectedScriptManager::canAccessInspectedWindow(ScriptState* scriptState) +{ + v8::HandleScope handleScope; + v8::Local<v8::Context> context = scriptState->context(); + v8::Local<v8::Object> global = context->Global(); + if (global.IsEmpty()) + return false; + v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), global); + if (holder.IsEmpty()) + return false; + Frame* frame = V8DOMWindow::toNative(holder)->frame(); + + v8::Context::Scope contextScope(context); + return V8BindingSecurity::canAccessFrame(V8BindingState::Only(), frame, false); +} + +} // namespace WebCore diff --git a/Source/WebCore/bindings/v8/custom/V8WebKitAnimationCustom.cpp b/Source/WebCore/bindings/v8/custom/V8WebKitAnimationCustom.cpp new file mode 100644 index 0000000..c0949ae --- /dev/null +++ b/Source/WebCore/bindings/v8/custom/V8WebKitAnimationCustom.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "V8WebKitAnimation.h" + +#include "V8Binding.h" +#include "V8BindingMacros.h" +#include "V8Proxy.h" +#include "WebKitAnimation.h" + +#include <v8.h> + +namespace WebCore { + +v8::Handle<v8::Value> V8WebKitAnimation::iterationCountAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.WebKitAnimation.iterationCount._get"); + v8::Handle<v8::Object> holder = info.Holder(); + WebKitAnimation* imp = V8WebKitAnimation::toNative(holder); + int count = imp->iterationCount(); + if (count == Animation::IterationCountInfinite) + return v8::Number::New(std::numeric_limits<float>::infinity()); + return v8::Number::New(count); +} + +} // namespace WebCore + |