Title: [87315] trunk/Source
Revision
87315
Author
caio.olive...@openbossa.org
Date
2011-05-25 12:28:22 -0700 (Wed, 25 May 2011)

Log Message

2011-05-25  Caio Marcelo de Oliveira Filho  <caio.olive...@openbossa.org>

        Reviewed by Andreas Kling.

        [Qt] JSC bridge: implement __qt_sender__ without using Scope Chain
        https://bugs.webkit.org/show_bug.cgi?id=61343

        Create a stack to keep track of the sender objects. This is simpler than
        the similar mechanism in QObject (C++ API), that keeps a stack per-object.

        Since we do not support multiple threads, one static stack will be enough for
        handling the behavior.

        This behavior is covered by the tst_QWebFrame::connectAndDisconnect() auto test.

        * bridge/qt/qt_instance.cpp:
        (JSC::Bindings::QtInstance::qtSenderStack):
        We have one static stack of QObject*. The top of the stack contains the
        last object that emitted signal that called a _javascript_ function.

        * bridge/qt/qt_instance.h:
        (JSC::Bindings::QtInstance::QtSenderStack::top):
        (JSC::Bindings::QtInstance::QtSenderStack::push):
        (JSC::Bindings::QtInstance::QtSenderStack::pop):
        Minimal functionality to manipulate the sender stack.

        * bridge/qt/qt_runtime.cpp:
        (JSC::Bindings::QtConnectionObject::execute):
        Remove the previous code that modified the scope chain. Push the sender object
        to the stack before calling the _javascript_ function (the "slot" in Qt-speak) and
        pop it afterwards.
2011-05-25  Caio Marcelo de Oliveira Filho  <caio.olive...@openbossa.org>

        Reviewed by Andreas Kling.

        [Qt] JSC bridge: implement __qt_sender__ without using Scope Chain
        https://bugs.webkit.org/show_bug.cgi?id=61343

        Create a '__qt_sender__' property in the global object, that returns the top of
        the qtSenderStack. This is an alternative implementation for the feature of
        providing a way for a function (acting as a Qt 'slot') discover which object
        emitted the signal that caused it to be executed.

        This reduces the coupling of the Qt bridge and JSC internal implementation. The
        patch tries to use as much JSC public API as possible.

        This behavior is covered by the tst_QWebFrame::connectAndDisconnect() auto test.

        * WebCoreSupport/FrameLoaderClientQt.cpp:
        (WebCore::FrameLoaderClientQt::dispatchDidClearWindowObjectInWorld):
        Instead of emitting the QWebPage::_javascript_WindowObjectCleared() directly, calls
        a QWebPagePrivate function to do it.

        * Api/qwebframe_p.h:
        * Api/qwebframe.cpp:
        (QWebFramePrivate::didClearedWindowObject):
        Before emitting the signal mentioned, adds the '__qt_sender__' to the fresh
        global object.

        (qtSenderCallback):
        Returns the JSObjectRef corresponding to the top of qtSenderStack.

        (QWebFramePrivate::addQtSenderToGlobalObject):
        Create a property with a qtSenderCallback as getter function in the global object.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (87314 => 87315)


--- trunk/Source/WebCore/ChangeLog	2011-05-25 19:25:50 UTC (rev 87314)
+++ trunk/Source/WebCore/ChangeLog	2011-05-25 19:28:22 UTC (rev 87315)
@@ -1,3 +1,35 @@
+2011-05-25  Caio Marcelo de Oliveira Filho  <caio.olive...@openbossa.org>
+
+        Reviewed by Andreas Kling.
+
+        [Qt] JSC bridge: implement __qt_sender__ without using Scope Chain
+        https://bugs.webkit.org/show_bug.cgi?id=61343
+
+        Create a stack to keep track of the sender objects. This is simpler than
+        the similar mechanism in QObject (C++ API), that keeps a stack per-object.
+
+        Since we do not support multiple threads, one static stack will be enough for
+        handling the behavior.
+
+        This behavior is covered by the tst_QWebFrame::connectAndDisconnect() auto test.
+
+        * bridge/qt/qt_instance.cpp:
+        (JSC::Bindings::QtInstance::qtSenderStack):
+        We have one static stack of QObject*. The top of the stack contains the
+        last object that emitted signal that called a _javascript_ function.
+
+        * bridge/qt/qt_instance.h:
+        (JSC::Bindings::QtInstance::QtSenderStack::top):
+        (JSC::Bindings::QtInstance::QtSenderStack::push):
+        (JSC::Bindings::QtInstance::QtSenderStack::pop):
+        Minimal functionality to manipulate the sender stack.
+
+        * bridge/qt/qt_runtime.cpp:
+        (JSC::Bindings::QtConnectionObject::execute):
+        Remove the previous code that modified the scope chain. Push the sender object
+        to the stack before calling the _javascript_ function (the "slot" in Qt-speak) and
+        pop it afterwards.
+
 2011-05-25  Sheriff Bot  <webkit.review....@gmail.com>
 
         Unreviewed, rolling out r87257.

Modified: trunk/Source/WebCore/bridge/qt/qt_instance.cpp (87314 => 87315)


--- trunk/Source/WebCore/bridge/qt/qt_instance.cpp	2011-05-25 19:25:50 UTC (rev 87314)
+++ trunk/Source/WebCore/bridge/qt/qt_instance.cpp	2011-05-25 19:28:22 UTC (rev 87315)
@@ -44,6 +44,9 @@
 typedef QMultiHash<void*, QtInstance*> QObjectInstanceMap;
 static QObjectInstanceMap cachedInstances;
 
+// Used for implementing '__qt_sender__'.
+Q_GLOBAL_STATIC(QtInstance::QtSenderStack, senderStack)
+
 // Derived RuntimeObject
 class QtRuntimeObject : public RuntimeObject {
 public:
@@ -321,6 +324,11 @@
     return stringValue(exec);
 }
 
+QtInstance::QtSenderStack* QtInstance::qtSenderStack()
+{
+    return senderStack();
+}
+
 // In qt_runtime.cpp
 JSValue convertQVariantToValue(ExecState*, PassRefPtr<RootObject> root, const QVariant& variant);
 QVariant convertValueToQVariant(ExecState*, JSValue, QMetaType::Type hint, int *distance);

Modified: trunk/Source/WebCore/bridge/qt/qt_instance.h (87314 => 87315)


--- trunk/Source/WebCore/bridge/qt/qt_instance.h	2011-05-25 19:25:50 UTC (rev 87314)
+++ trunk/Source/WebCore/bridge/qt/qt_instance.h	2011-05-25 19:28:22 UTC (rev 87315)
@@ -22,6 +22,7 @@
 
 #include "BridgeJSC.h"
 #include "runtime_root.h"
+#include <QStack>
 #include <QtScript/qscriptengine.h>
 #include <qhash.h>
 #include <qpointer.h>
@@ -71,6 +72,18 @@
 
     static QtInstance* getInstance(JSObject*);
 
+    class QtSenderStack {
+    public:
+        QObject* top() const { return m_stack.isEmpty() ? 0 : m_stack.top(); }
+        void push(QObject* object) { m_stack.push(object); }
+        void pop() { Q_ASSERT(!m_stack.isEmpty()); m_stack.pop(); }
+    private:
+        QStack<QObject*> m_stack;
+    };
+
+    // Used to implement '__qt_sender__'.
+    static QtSenderStack* qtSenderStack();
+
 private:
     static PassRefPtr<QtInstance> create(QObject *instance, PassRefPtr<RootObject> rootObject, QScriptEngine::ValueOwnership ownership)
     {

Modified: trunk/Source/WebCore/bridge/qt/qt_runtime.cpp (87314 => 87315)


--- trunk/Source/WebCore/bridge/qt/qt_runtime.cpp	2011-05-25 19:25:50 UTC (rev 87314)
+++ trunk/Source/WebCore/bridge/qt/qt_runtime.cpp	2011-05-25 19:28:22 UTC (rev 87315)
@@ -1838,26 +1838,17 @@
                             l.append(jsUndefined());
                         }
                     }
-                    // Stuff in the __qt_sender property, if we can
-                    ScopeChainNode* oldsc = 0;
-                    JSFunction* fimp = 0;
-                    if (m_funcObject->inherits(&JSFunction::s_info)) {
-                        fimp = static_cast<JSFunction*>(m_funcObject.get());
 
-                        JSObject* qt_sender = QtInstance::getQtInstance(sender(), ro, QScriptEngine::QtOwnership)->createRuntimeObject(exec);
-                        JSObject* wrapper = constructEmptyObject(exec, createEmptyObjectStructure(exec->globalData(), jsNull()));
-                        PutPropertySlot slot;
-                        wrapper->put(exec, Identifier(exec, "__qt_sender__"), qt_sender, slot);
-                        oldsc = fimp->scope();
-                        fimp->setScope(exec->globalData(), oldsc->push(wrapper));
-                    }
+                    const bool withQtSenderStack = m_funcObject->inherits(&JSFunction::s_info);
+                    if (withQtSenderStack)
+                        QtInstance::qtSenderStack()->push(QObject::sender());
 
                     CallData callData;
                     CallType callType = m_funcObject->getCallData(callData);
                     call(exec, m_funcObject.get(), callType, callData, m_thisObject.get(), l);
 
-                    if (fimp)
-                        fimp->setScope(exec->globalData(), oldsc);
+                    if (withQtSenderStack)
+                        QtInstance::qtSenderStack()->pop();
                 }
             }
         }

Modified: trunk/Source/WebKit/qt/Api/qwebframe.cpp (87314 => 87315)


--- trunk/Source/WebKit/qt/Api/qwebframe.cpp	2011-05-25 19:25:50 UTC (rev 87314)
+++ trunk/Source/WebKit/qt/Api/qwebframe.cpp	2011-05-25 19:28:22 UTC (rev 87315)
@@ -22,6 +22,7 @@
 #include "qwebframe.h"
 
 #if USE(JSC)
+#include "APICast.h"
 #include "BridgeJSC.h"
 #include "CallFrame.h"
 #elif USE(V8)
@@ -49,10 +50,13 @@
 #include "IconDatabase.h"
 #include "InspectorController.h"
 #if USE(JSC)
+#include "_javascript_.h"
 #include "JSDOMBinding.h"
 #include "JSDOMWindowBase.h"
 #include "JSLock.h"
 #include "JSObject.h"
+#include "JSRetainPtr.h"
+#include "OpaqueJSString.h"
 #elif USE(V8)
 #include "V8DOMWrapper.h"
 #include "V8DOMWindowShell.h"
@@ -471,6 +475,49 @@
     frame->sendOrientationChangeEvent(orientation);
 #endif
 }
+
+void QWebFramePrivate::didClearWindowObject()
+{
+#if USE(JSC)
+    if (page->settings()->testAttribute(QWebSettings::_javascript_Enabled))
+        addQtSenderToGlobalObject();
+#endif
+    emit q->_javascript_WindowObjectCleared();
+}
+
+#if USE(JSC)
+static JSValueRef qtSenderCallback(JSContextRef context, JSObjectRef, JSObjectRef, size_t, const JSValueRef[], JSValueRef*)
+{
+    QObject* sender = JSC::Bindings::QtInstance::qtSenderStack()->top();
+    if (!sender)
+        return JSValueMakeUndefined(context);
+
+    JSC::ExecState* exec = ::toJS(context);
+    RefPtr<JSC::Bindings::RootObject> rootObject = JSC::Bindings::findRootObject(exec->dynamicGlobalObject());
+    JSC::JSObject* jsSender = JSC::Bindings::QtInstance::getQtInstance(sender, rootObject, QScriptEngine::QtOwnership)->createRuntimeObject(exec);
+    return ::toRef(jsSender);
+}
+
+void QWebFramePrivate::addQtSenderToGlobalObject()
+{
+    JSC::JSLock lock(JSC::SilenceAssertionsOnly);
+
+    JSDOMWindow* window = toJSDOMWindow(frame, mainThreadNormalWorld());
+    Q_ASSERT(window);
+
+    JSC::ExecState* exec = window->globalExec();
+    Q_ASSERT(exec);
+
+    JSContextRef context = ::toRef(exec);
+    JSRetainPtr<JSStringRef> propertyName(Adopt, JSStringCreateWithUTF8CString("__qt_sender__"));
+    JSObjectRef function = JSObjectMakeFunctionWithCallback(context, propertyName.get(), qtSenderCallback);
+
+    // JSC public API doesn't support setting a Getter for a property of a given object, https://bugs.webkit.org/show_bug.cgi?id=61374.
+    window->defineGetter(exec, propertyName.get()->identifier(&exec->globalData()), ::toJS(function),
+                         JSC::ReadOnly | JSC::DontEnum | JSC::DontDelete);
+}
+#endif
+
 /*!
     \class QWebFrame
     \since 4.4

Modified: trunk/Source/WebKit/qt/Api/qwebframe_p.h (87314 => 87315)


--- trunk/Source/WebKit/qt/Api/qwebframe_p.h	2011-05-25 19:25:50 UTC (rev 87314)
+++ trunk/Source/WebKit/qt/Api/qwebframe_p.h	2011-05-25 19:28:22 UTC (rev 87315)
@@ -108,6 +108,8 @@
     void emitUrlChanged();
     void _q_orientationChanged();
 
+    void didClearWindowObject();
+
     QWebFrame *q;
     Qt::ScrollBarPolicy horizontalScrollBarPolicy;
     Qt::ScrollBarPolicy verticalScrollBarPolicy;
@@ -127,6 +129,11 @@
 #if ENABLE(ORIENTATION_EVENTS) && ENABLE(DEVICE_ORIENTATION)
     QtMobility::QOrientationSensor m_orientation;
 #endif
+
+private:
+#if USE(JSC)
+    void addQtSenderToGlobalObject();
+#endif
 };
 
 class QWebHitTestResultPrivate {

Modified: trunk/Source/WebKit/qt/ChangeLog (87314 => 87315)


--- trunk/Source/WebKit/qt/ChangeLog	2011-05-25 19:25:50 UTC (rev 87314)
+++ trunk/Source/WebKit/qt/ChangeLog	2011-05-25 19:28:22 UTC (rev 87315)
@@ -1,3 +1,37 @@
+2011-05-25  Caio Marcelo de Oliveira Filho  <caio.olive...@openbossa.org>
+
+        Reviewed by Andreas Kling.
+
+        [Qt] JSC bridge: implement __qt_sender__ without using Scope Chain
+        https://bugs.webkit.org/show_bug.cgi?id=61343
+
+        Create a '__qt_sender__' property in the global object, that returns the top of
+        the qtSenderStack. This is an alternative implementation for the feature of
+        providing a way for a function (acting as a Qt 'slot') discover which object
+        emitted the signal that caused it to be executed.
+
+        This reduces the coupling of the Qt bridge and JSC internal implementation. The
+        patch tries to use as much JSC public API as possible.
+
+        This behavior is covered by the tst_QWebFrame::connectAndDisconnect() auto test.
+
+        * WebCoreSupport/FrameLoaderClientQt.cpp:
+        (WebCore::FrameLoaderClientQt::dispatchDidClearWindowObjectInWorld):
+        Instead of emitting the QWebPage::_javascript_WindowObjectCleared() directly, calls
+        a QWebPagePrivate function to do it.
+
+        * Api/qwebframe_p.h:
+        * Api/qwebframe.cpp:
+        (QWebFramePrivate::didClearedWindowObject):
+        Before emitting the signal mentioned, adds the '__qt_sender__' to the fresh
+        global object.
+
+        (qtSenderCallback):
+        Returns the JSObjectRef corresponding to the top of qtSenderStack.
+
+        (QWebFramePrivate::addQtSenderToGlobalObject):
+        Create a property with a qtSenderCallback as getter function in the global object.
+
 2011-05-25  Alexis Menard  <alexis.men...@openbossa.org>
 
         Reviewed by Eric Carlson.

Modified: trunk/Source/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp (87314 => 87315)


--- trunk/Source/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp	2011-05-25 19:25:50 UTC (rev 87314)
+++ trunk/Source/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp	2011-05-25 19:28:22 UTC (rev 87315)
@@ -763,7 +763,7 @@
         return;
 
     if (m_webFrame)
-        emit m_webFrame->_javascript_WindowObjectCleared();
+        m_webFrame->d->didClearWindowObject();
 }
 
 void FrameLoaderClientQt::documentElementAvailable()
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to