Changeset 88635 in webkit
- Timestamp:
- Jun 13, 2011 6:41:44 AM (13 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r88634 r88635 1 2011-06-13 Caio Marcelo de Oliveira Filho <caio.oliveira@openbossa.org> 2 3 Reviewed by Andreas Kling. 4 5 [Qt] JSC Bridge: convert QtConnectionObject to use JSC API 6 https://bugs.webkit.org/show_bug.cgi?id=62330 7 8 This patch is based on the draft patch by Noam Rosenthal in bug 60842. 9 Qt API autotests cover the bridge behavior and pass after this patch. 10 11 * bridge/qt/qt_runtime.h: Change QtConnectionObject to use JSC API types. In 12 particular, we got rid of Strong<JSObject> members. Renamed some members and 13 arguments to follow existing naming in QObject::connect(). 14 15 * bridge/qt/qt_runtime.cpp: 16 (JSC::Bindings::QtRuntimeConnectionMethod::call): Use a new helper function 17 to create a connection, passing the ExecState* that will be used when the 18 connection is activated (signal emitted). Use JSC API types when looking up 19 the matching signal to disconnect. 20 21 (JSC::Bindings::QtConnectionObject::QtConnectionObject): Use JSC API to 22 protect the receiver and receiverFunction from being garbage 23 collected. Removed the ASSERT() since we don't hold ProtectedPtrs (in current 24 code were Strong<>) anymore. 25 26 (JSC::Bindings::QtConnectionObject::~QtConnectionObject): Explain why is safe 27 to use m_originalSender here. Unprotect values that we protected in constructor. 28 29 (JSC::Bindings::isJavaScriptFunction): Helper function to identify whether a 30 JSObjectRef is a JS function (in contrast to a native function exposed to JS). 31 32 (JSC::Bindings::QtConnectionObject::execute): 33 (JSC::Bindings::QtConnectionObject::match): 34 Both updated to use JSC API when appliable. Note that convertQVariantToValue 35 still returns JSC internal types, will be handled in a different patch. 36 37 (JSC::Bindings::QtConnectionObject::createWithInternalJSC): 38 Convenince for the existing caller until it is converted to JSC as well. 39 1 40 2011-06-13 Carlos Garcia Campos <cgarcia@igalia.com> 2 41 -
trunk/Source/WebCore/bridge/qt/qt_runtime.cpp
r87346 r88635 21 21 #include "qt_runtime.h" 22 22 23 #include "APICast.h" 23 24 #include "BooleanObject.h" 24 25 #include "DateInstance.h" … … 38 39 #include "JSLock.h" 39 40 #include "JSObject.h" 41 #include "JSRetainPtr.h" 40 42 #include "ObjectPrototype.h" 41 43 #include "PropertyNameArray.h" … … 1643 1645 // receiver this object [from arguments] 1644 1646 1645 QtConnectionObject* conn = new QtConnectionObject(exec->globalData(), d->m_instance, signalIndex, thisObject, funcObject); 1647 ExecState* globalExec = exec->lexicalGlobalObject()->globalExec(); 1648 QtConnectionObject* conn = QtConnectionObject::createWithInternalJSC(globalExec, d->m_instance, signalIndex, thisObject, funcObject); 1646 1649 bool ok = QMetaObject::connect(sender, signalIndex, conn, conn->metaObject()->methodOffset()); 1647 1650 if (!ok) { … … 1661 1664 bool ret = false; 1662 1665 1666 JSContextRef context = ::toRef(exec); 1667 JSObjectRef receiver = ::toRef(thisObject); 1668 JSObjectRef receiverFunction = ::toRef(funcObject); 1669 1663 1670 foreach(QtConnectionObject* conn, conns) { 1664 1671 // Is this the right connection? 1665 if (conn->match( sender, signalIndex, thisObject, funcObject)) {1672 if (conn->match(context, sender, signalIndex, receiver, receiverFunction)) { 1666 1673 // Yep, disconnect it 1667 1674 QMetaObject::disconnect(sender, signalIndex, conn, conn->metaObject()->methodOffset()); … … 1737 1744 // =============== 1738 1745 1739 QtConnectionObject::QtConnectionObject(JSGlobalData& globalData, PassRefPtr<QtInstance> instance, int signalIndex, JSObject* thisObject, JSObject* funcObject) 1740 : m_instance(instance) 1746 QtConnectionObject::QtConnectionObject(JSContextRef context, PassRefPtr<QtInstance> senderInstance, int signalIndex, JSObjectRef receiver, JSObjectRef receiverFunction) 1747 : QObject(senderInstance->getObject()) 1748 , m_context(context) 1749 , m_senderInstance(senderInstance) 1750 , m_originalSender(m_senderInstance->getObject()) 1741 1751 , m_signalIndex(signalIndex) 1742 , m_originalObject(m_instance->getObject()) 1743 , m_thisObject(globalData, thisObject) 1744 , m_funcObject(globalData, funcObject) 1745 { 1746 setParent(m_originalObject); 1747 ASSERT(JSLock::currentThreadIsHoldingLock()); // so our ProtectedPtrs are safe 1752 , m_receiver(receiver) 1753 , m_receiverFunction(receiverFunction) 1754 { 1755 JSValueProtect(m_context, m_receiver); 1756 JSValueProtect(m_context, m_receiverFunction); 1748 1757 } 1749 1758 1750 1759 QtConnectionObject::~QtConnectionObject() 1751 1760 { 1752 // Remove us from the map of active connections 1753 QtRuntimeConnectionMethod::connections.remove(m_originalObject, this); 1761 // We can safely use m_originalSender because connection object will never outlive the sender, 1762 // which is its QObject parent. 1763 QtRuntimeConnectionMethod::connections.remove(m_originalSender, this); 1764 1765 JSValueUnprotect(m_context, m_receiver); 1766 JSValueUnprotect(m_context, m_receiverFunction); 1754 1767 } 1755 1768 … … 1792 1805 } 1793 1806 1807 // This is what moc would generate except by the fact that we pass all arguments to our execute() slot. 1794 1808 int QtConnectionObject::qt_metacall(QMetaObject::Call _c, int _id, void **_a) 1795 1809 { … … 1806 1820 } 1807 1821 1808 void QtConnectionObject::execute(void **argv) 1809 { 1810 QObject* obj = m_instance->getObject(); 1811 if (obj) { 1812 const QMetaObject* meta = obj->metaObject(); 1813 const QMetaMethod method = meta->method(m_signalIndex); 1814 1815 QList<QByteArray> parameterTypes = method.parameterTypes(); 1816 1817 int argc = parameterTypes.count(); 1818 1819 JSLock lock(SilenceAssertionsOnly); 1820 1821 // ### Should the Interpreter/ExecState come from somewhere else? 1822 RefPtr<RootObject> ro = m_instance->rootObject(); 1823 if (ro) { 1824 JSGlobalObject* globalobj = ro->globalObject(); 1825 if (globalobj) { 1826 ExecState* exec = globalobj->globalExec(); 1827 if (exec) { 1828 // Build the argument list (up to the formal argument length of the slot) 1829 MarkedArgumentBuffer l; 1830 // ### DropAllLocks? 1831 int funcArgC = m_funcObject->get(exec, exec->propertyNames().length).toInt32(exec); 1832 int argTotal = qMax(funcArgC, argc); 1833 for(int i=0; i < argTotal; i++) { 1834 if (i < argc) { 1835 int argType = QMetaType::type(parameterTypes.at(i)); 1836 l.append(convertQVariantToValue(exec, ro, QVariant(argType, argv[i+1]))); 1837 } else { 1838 l.append(jsUndefined()); 1839 } 1840 } 1841 1842 const bool withQtSenderStack = m_funcObject->inherits(&JSFunction::s_info); 1843 if (withQtSenderStack) 1844 QtInstance::qtSenderStack()->push(QObject::sender()); 1845 1846 CallData callData; 1847 CallType callType = m_funcObject->getCallData(callData); 1848 call(exec, m_funcObject.get(), callType, callData, m_thisObject.get(), l); 1849 1850 if (withQtSenderStack) 1851 QtInstance::qtSenderStack()->pop(); 1852 } 1853 } 1854 } 1855 } else { 1856 // A strange place to be - a deleted object emitted a signal here. 1822 static bool isJavaScriptFunction(JSObjectRef object) 1823 { 1824 CallData callData; 1825 return toJS(object)->getCallData(callData) == CallTypeJS; 1826 } 1827 1828 void QtConnectionObject::execute(void** argv) 1829 { 1830 QObject* sender = m_senderInstance->getObject(); 1831 if (!sender) { 1857 1832 qWarning() << "sender deleted, cannot deliver signal"; 1858 } 1859 } 1860 1861 bool QtConnectionObject::match(QObject* sender, int signalIndex, JSObject* thisObject, JSObject *funcObject) 1862 { 1863 if (m_originalObject == sender && m_signalIndex == signalIndex 1864 && thisObject == (JSObject*)m_thisObject.get() && funcObject == (JSObject*)m_funcObject.get()) 1865 return true; 1866 return false; 1833 return; 1834 } 1835 1836 ASSERT(sender == m_originalSender); 1837 1838 const QMetaObject* meta = sender->metaObject(); 1839 const QMetaMethod method = meta->method(m_signalIndex); 1840 1841 QList<QByteArray> parameterTypes = method.parameterTypes(); 1842 1843 JSValueRef* ignoredException = 0; 1844 JSRetainPtr<JSStringRef> lengthProperty(JSStringCreateWithUTF8CString("length")); 1845 int receiverLength = int(JSValueToNumber(m_context, JSObjectGetProperty(m_context, m_receiverFunction, lengthProperty.get(), ignoredException), ignoredException)); 1846 int argc = qMax(parameterTypes.count(), receiverLength); 1847 WTF::Vector<JSValueRef> args(argc); 1848 1849 // TODO: remove once conversion functions use JSC API. 1850 ExecState* exec = ::toJS(m_context); 1851 RefPtr<RootObject> rootObject = m_senderInstance->rootObject(); 1852 1853 for (int i = 0; i < argc; i++) { 1854 int argType = QMetaType::type(parameterTypes.at(i)); 1855 args[i] = ::toRef(exec, convertQVariantToValue(exec, rootObject, QVariant(argType, argv[i+1]))); 1856 } 1857 1858 const bool updateQtSender = isJavaScriptFunction(m_receiverFunction); 1859 if (updateQtSender) 1860 QtInstance::qtSenderStack()->push(QObject::sender()); 1861 1862 JSObjectCallAsFunction(m_context, m_receiverFunction, m_receiver, argc, args.data(), 0); 1863 1864 if (updateQtSender) 1865 QtInstance::qtSenderStack()->pop(); 1866 } 1867 1868 bool QtConnectionObject::match(JSContextRef context, QObject* sender, int signalIndex, JSObjectRef receiver, JSObjectRef receiverFunction) 1869 { 1870 if (sender != m_originalSender || signalIndex != m_signalIndex) 1871 return false; 1872 JSValueRef* ignoredException = 0; 1873 const bool receiverMatch = (!receiver && !m_receiver) || JSValueIsEqual(context, receiver, m_receiver, ignoredException); 1874 return receiverMatch && JSValueIsEqual(context, receiverFunction, m_receiverFunction, ignoredException); 1875 } 1876 1877 QtConnectionObject* QtConnectionObject::createWithInternalJSC(ExecState* exec, PassRefPtr<QtInstance> senderInstance, int signalIndex, JSObject* receiver, JSObject* receiverFunction) 1878 { 1879 return new QtConnectionObject(::toRef(exec), senderInstance, signalIndex, ::toRef(receiver), ::toRef(receiverFunction)); 1867 1880 } 1868 1881 -
trunk/Source/WebCore/bridge/qt/qt_runtime.h
r88361 r88635 22 22 23 23 #include "BridgeJSC.h" 24 #include "Completion.h" 25 #include "Strong.h" 24 #include "JavaScript.h" 26 25 #include "Weak.h" 27 26 #include "runtime_method.h" … … 193 192 }; 194 193 195 class QtConnectionObject: public QObject 196 { 197 public: 198 QtConnectionObject(JSGlobalData&, PassRefPtr<QtInstance> instance, int signalIndex, JSObject* thisObject, JSObject* funcObject); 194 // A QtConnectionObject represents a connection created inside JS. It will connect its own execute() slot 195 // with the appropriate signal of 'sender'. When execute() is called, it will call JS 'receiverFunction'. 196 class QtConnectionObject : public QObject 197 { 198 public: 199 QtConnectionObject(JSContextRef, PassRefPtr<QtInstance> senderInstance, int signalIndex, JSObjectRef receiver, JSObjectRef receiverFunction); 199 200 ~QtConnectionObject(); 200 201 202 // Explicitly define these because want a custom qt_metacall(), so we can't use Q_OBJECT macro. 201 203 static const QMetaObject staticMetaObject; 202 204 virtual const QMetaObject *metaObject() const; … … 204 206 virtual int qt_metacall(QMetaObject::Call, int, void **argv); 205 207 206 bool match(QObject *sender, int signalIndex, JSObject* thisObject, JSObject *funcObject);207 208 // actual slot:209 208 void execute(void **argv); 210 209 211 private: 212 RefPtr<QtInstance> m_instance; 210 bool match(JSContextRef, QObject* sender, int signalIndex, JSObjectRef thisObject, JSObjectRef funcObject); 211 212 // Note: for callers using JSC internals, remove once we don't need anymore. 213 static QtConnectionObject* createWithInternalJSC(ExecState*, PassRefPtr<QtInstance> senderInstance, int signalIndex, JSObject* receiver, JSObject* receiverFunction); 214 215 private: 216 JSContextRef m_context; 217 RefPtr<QtInstance> m_senderInstance; 218 219 // We use this as key in active connections multimap. 220 QObject* m_originalSender; 221 213 222 int m_signalIndex; 214 QObject* m_originalObject; // only used as a key, not dereferenced 215 Strong<JSObject> m_thisObject; 216 Strong<JSObject> m_funcObject; 223 JSObjectRef m_receiver; 224 JSObjectRef m_receiverFunction; 217 225 }; 218 226
Note: See TracChangeset
for help on using the changeset viewer.