Changeset 125428 in webkit
- Timestamp:
- Aug 13, 2012 10:53:33 AM (12 years ago)
- Location:
- trunk/Source
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r125427 r125428 1 2012-08-13 Simon Hausmann <simon.hausmann@nokia.com> 2 3 [Qt] Port meta method/signal/slot handling in run-time bridge to use JSC C API 4 https://bugs.webkit.org/show_bug.cgi?id=93476 5 6 Reviewed by Kenneth Rohde Christiansen. 7 8 Based on patch by No'am Rosenthal and lots of good suggestions by Caio Marcelo. 9 10 Ported the code that mapped invokable methods (and signals/slots) as 11 well as the code that provides the connect() and disconnect() functions 12 over to use the JSC C API. In the process one behavioural change was 13 implemented: Previously meta methods were actually function objects 14 that through Function.prototype allowed calling via 15 object.method.call(object). Through the use of plain JS objects that is 16 not possible anymore. 17 18 If we tried to continue to use function objects (JSObjectMakeFunction) 19 then we would loose the ability to store the private pointer. An 20 alternative approach would be to use a regular object and install the 21 Function prototype (Function.prototype), but unfortunately we cannot do 22 that without loosing the common prototype for signals and slots. 23 24 * bridge/qt/qt_class.cpp: 25 (JSC::Bindings::QtClass::fallbackObject): 26 * bridge/qt/qt_instance.cpp: 27 (JSC::Bindings::QtInstance::~QtInstance): 28 (JSC::Bindings::QtInstance::newRuntimeObject): 29 * bridge/qt/qt_instance.h: 30 (Bindings): 31 (QtInstance): 32 * bridge/qt/qt_runtime.cpp: 33 (JSC::Bindings::prototypeForSignalsAndSlots): 34 (JSC::Bindings::QtRuntimeMethod::QtRuntimeMethod): 35 (JSC::Bindings::QtRuntimeMethod::~QtRuntimeMethod): 36 (JSC::Bindings::QtRuntimeMethod::call): 37 (JSC::Bindings::QtRuntimeMethod::connect): 38 (JSC::Bindings::QtRuntimeMethod::disconnect): 39 (JSC::Bindings::QtRuntimeMethod::jsObjectRef): 40 (JSC::Bindings::QtRuntimeMethod::connectOrDisconnect): 41 (Bindings): 42 (JSC::Bindings::QtConnectionObject::~QtConnectionObject): 43 * bridge/qt/qt_runtime.h: 44 (JSC::Bindings::QtRuntimeMethod::name): 45 (QtRuntimeMethod): 46 (QtConnectionObject): 47 1 48 2012-08-13 Leandro Gracia Gil <leandrogracia@chromium.org> 2 49 -
trunk/Source/WebCore/bridge/qt/qt_class.cpp
r124879 r125428 21 21 #include "qt_class.h" 22 22 23 #include "APICast.h" 23 24 #include "Identifier.h" 24 25 #include "qt_instance.h" … … 70 71 { 71 72 QtInstance* qtinst = static_cast<QtInstance*>(inst); 73 JSContextRef context = toRef(exec); 74 JSValueRef* exception = 0; 72 75 73 76 UString ustring(identifier.publicName()); … … 75 78 76 79 // First see if we have a cache hit 77 JSObject* val = qtinst->m_methods.value(name).get(); 78 if (val) 79 return val; 80 if (QtRuntimeMethod* method = qtinst->m_methods.value(name)) 81 return toJS(method->jsObjectRef(context, exception)); 80 82 81 83 // Nope, create an entry … … 84 86 // See if there is an exact match 85 87 int index = -1; 88 QMetaMethod metaMethod; 86 89 if (normal.contains('(') && (index = m_metaObject->indexOfMethod(normal)) != -1) { 87 QMetaMethod m = m_metaObject->method(index); 88 if (m.access() != QMetaMethod::Private) { 89 QtRuntimeMetaMethod* val = QtRuntimeMetaMethod::create(exec, ustring, static_cast<QtInstance*>(inst), index, normal, false); 90 qtinst->m_methods.insert(name, val); 91 return val; 92 } 90 metaMethod = m_metaObject->method(index); 91 if (metaMethod.access() == QMetaMethod::Private) 92 index = -1; 93 93 } 94 94 95 95 // Nope.. try a basename match 96 const int count = m_metaObject->methodCount(); 97 for (index = count - 1; index >= 0; --index) { 98 const QMetaMethod m = m_metaObject->method(index); 99 if (m.access() == QMetaMethod::Private) 100 continue; 101 102 if (normal == m.name()) { 103 QtRuntimeMetaMethod* val = QtRuntimeMetaMethod::create(exec, ustring, static_cast<QtInstance*>(inst), index, normal, false); 104 qtinst->m_methods.insert(name, val); 105 return val; 106 } 107 } 108 109 return jsUndefined(); 96 if (index == -1) { 97 const int count = m_metaObject->methodCount(); 98 for (index = count - 1; index >= 0; --index) { 99 metaMethod = m_metaObject->method(index); 100 if (metaMethod.access() == QMetaMethod::Private) 101 continue; 102 103 if (metaMethod.name() == normal) 104 break; 105 } 106 } 107 108 if (index == -1) 109 return jsUndefined(); 110 111 int flags = metaMethod.methodType() == QMetaMethod::Signal ? QtRuntimeMethod::MethodIsSignal : 0; 112 QtRuntimeMethod* method = new QtRuntimeMethod(context, exception, static_cast<QtInstance*>(inst)->getObject(), normal, index, flags, qtinst); 113 qtinst->m_methods.insert(name, method); 114 return toJS(method->jsObjectRef(context, exception)); 110 115 } 111 116 -
trunk/Source/WebCore/bridge/qt/qt_instance.cpp
r125253 r125428 95 95 cachedInstances.remove(m_hashkey); 96 96 97 // clean up (unprotect from gc) the JSValues we've created97 qDeleteAll(m_methods); 98 98 m_methods.clear(); 99 99 … … 148 148 } 149 149 150 void QtInstance::removeUnusedMethods()151 {152 for (QHash<QByteArray, QtWeakObjectReference>::Iterator it = m_methods.begin(), end = m_methods.end(); it != end; ) {153 if (!it.value().get())154 it = m_methods.erase(it);155 else156 ++it;157 }158 }159 160 150 QtInstance* QtInstance::getInstance(JSObject* object) 161 151 { … … 180 170 { 181 171 JSLockHolder lock(exec); 172 qDeleteAll(m_methods); 182 173 m_methods.clear(); 183 174 return QtRuntimeObject::create(exec, exec->lexicalGlobalObject(), this); -
trunk/Source/WebCore/bridge/qt/qt_instance.h
r125355 r125428 34 34 class QtClass; 35 35 class QtField; 36 class QtRuntimeMet aMethod;36 class QtRuntimeMethod; 37 37 38 38 class QtInstance : public Instance { … … 72 72 virtual void put(JSObject*, ExecState*, PropertyName, JSValue, PutPropertySlot&); 73 73 74 void removeUnusedMethods();75 76 74 static QtInstance* getInstance(JSObject*); 77 75 78 76 private: 79 80 class QtWeakObjectReference {81 public:82 QtWeakObjectReference(JSObject* reference)83 : m_reference(reference)84 {85 }86 87 QtWeakObjectReference(const QtWeakObjectReference& source)88 : m_reference(source.m_reference.get())89 {90 }91 92 QtWeakObjectReference()93 : m_reference()94 {95 }96 97 QtWeakObjectReference& operator=(const QtWeakObjectReference& source)98 {99 m_reference = PassWeak<JSObject>(source.m_reference.get());100 return *this;101 }102 103 JSObject* get() const104 {105 return m_reference.get();106 }107 108 private:109 Weak<JSObject> m_reference;110 };111 112 77 static PassRefPtr<QtInstance> create(QObject *instance, PassRefPtr<RootObject> rootObject, ValueOwnership ownership) 113 78 { … … 121 86 QPointer<QObject> m_object; 122 87 QObject* m_hashkey; 123 mutable QHash<QByteArray, Qt WeakObjectReference> m_methods;88 mutable QHash<QByteArray, QtRuntimeMethod*> m_methods; 124 89 mutable QHash<QString, QtField*> m_fields; 125 90 ValueOwnership m_ownership; -
trunk/Source/WebCore/bridge/qt/qt_runtime.cpp
r125276 r125428 914 914 } 915 915 916 // ===============917 918 // Qt-like macros919 #define QW_D(Class) Class##Data* d = d_func()920 #define QW_DS(Class,Instance) Class##Data* d = Instance->d_func()921 922 const ClassInfo QtRuntimeMethod::s_info = { "QtRuntimeMethod", &InternalFunction::s_info, 0, 0, CREATE_METHOD_TABLE(QtRuntimeMethod) };923 924 QtRuntimeMethod::QtRuntimeMethod(QtRuntimeMethodData* dd, ExecState* exec, Structure* structure, const UString& identifier)925 : InternalFunction(exec->lexicalGlobalObject(), structure)926 , d_ptr(dd)927 {928 }929 930 void QtRuntimeMethod::finishCreation(ExecState* exec, const UString& identifier, PassRefPtr<QtInstance> instance)931 {932 Base::finishCreation(exec->globalData(), identifier);933 QW_D(QtRuntimeMethod);934 d->m_instance = instance;935 d->m_finalizer = PassWeak<QtRuntimeMethod>(this, d);936 }937 938 QtRuntimeMethod::~QtRuntimeMethod()939 {940 delete d_ptr;941 }942 943 void QtRuntimeMethod::destroy(JSCell* cell)944 {945 static_cast<QtRuntimeMethod*>(cell)->QtRuntimeMethod::~QtRuntimeMethod();946 }947 948 // ===============949 950 QtRuntimeMethodData::~QtRuntimeMethodData()951 {952 }953 954 void QtRuntimeMethodData::finalize(Handle<Unknown>, void*)955 {956 m_instance->removeUnusedMethods();957 }958 959 QtRuntimeMetaMethodData::~QtRuntimeMetaMethodData()960 {961 962 }963 964 QtRuntimeConnectionMethodData::~QtRuntimeConnectionMethodData()965 {966 967 }968 969 // ===============970 971 916 // Type conversion metadata (from QtScript originally) 972 917 class QtMethodMatchType … … 1336 1281 } 1337 1282 1338 const ClassInfo QtRuntimeMetaMethod::s_info = { "QtRuntimeMethod", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(QtRuntimeMetaMethod) }; 1339 1340 QtRuntimeMetaMethod::QtRuntimeMetaMethod(ExecState* exec, Structure* structure, const UString& identifier) 1341 : QtRuntimeMethod (new QtRuntimeMetaMethodData(), exec, structure, identifier) 1342 { 1343 } 1344 1345 void QtRuntimeMetaMethod::finishCreation(ExecState* exec, const UString& identifier, PassRefPtr<QtInstance> instance, int index, const QByteArray& signature, bool allowPrivate) 1346 { 1347 Base::finishCreation(exec, identifier, instance); 1348 QW_D(QtRuntimeMetaMethod); 1349 d->m_signature = signature; 1350 d->m_index = index; 1351 d->m_allowPrivate = allowPrivate; 1352 } 1353 1354 void QtRuntimeMetaMethod::visitChildren(JSCell* cell, SlotVisitor& visitor) 1355 { 1356 QtRuntimeMetaMethod* thisObject = jsCast<QtRuntimeMetaMethod*>(cell); 1357 QtRuntimeMethod::visitChildren(thisObject, visitor); 1358 QtRuntimeMetaMethodData* d = thisObject->d_func(); 1359 if (d->m_connect) 1360 visitor.append(&d->m_connect); 1361 if (d->m_disconnect) 1362 visitor.append(&d->m_disconnect); 1363 } 1364 1365 EncodedJSValue QtRuntimeMetaMethod::call(ExecState* exec) 1366 { 1367 QtRuntimeMetaMethodData* d = static_cast<QtRuntimeMetaMethod *>(exec->callee())->d_func(); 1368 1369 // We're limited to 10 args 1370 if (exec->argumentCount() > 10) 1371 return JSValue::encode(jsUndefined()); 1372 1373 // We have to pick a method that matches.. 1374 JSLockHolder lock(exec); 1375 1376 QObject *obj = d->m_instance->getObject(); 1377 if (obj) { 1378 const int argumentCount = static_cast<int>(exec->argumentCount()); 1379 Vector<JSValueRef, 10> args(argumentCount); 1380 for (int i = 0; i < argumentCount; ++i) 1381 args[i] = toRef(exec, exec->argument(i)); 1382 1383 QVarLengthArray<QVariant, 10> vargs; 1384 void *qargs[11]; 1385 1386 int methodIndex; 1387 JSValueRef exception = 0; 1388 if ((methodIndex = findMethodIndex(toRef(exec), obj->metaObject(), d->m_signature, argumentCount, args.data(), d->m_allowPrivate, vargs, (void **)qargs, &exception)) != -1) { 1389 if (QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, methodIndex, qargs) >= 0) 1390 return JSValue::encode(jsUndefined()); 1391 1392 if (vargs.size() > 0 && vargs[0].isValid()) 1393 return JSValue::encode(convertQVariantToValue(exec, d->m_instance->rootObject(), vargs[0])); 1394 } 1395 1396 if (exception) 1397 return throwVMError(exec, toJS(exec, exception)); 1283 static JSClassRef prototypeForSignalsAndSlots() 1284 { 1285 static JSClassDefinition classDef = { 1286 0, 0, 0, 0, 0, 0, 1287 0, 0, 0, 0, 0, 0, 0, QtRuntimeMethod::call, 0, 0, 0 1288 }; 1289 static JSClassRef cls = JSClassCreate(&classDef); 1290 return cls; 1291 } 1292 1293 QtRuntimeMethod::QtRuntimeMethod(JSContextRef ctx, JSValueRef* exception, QObject* object, const QByteArray& identifier, int index, int flags, QtInstance* instance) 1294 : m_object(object) 1295 , m_identifier(identifier) 1296 , m_index(index) 1297 , m_flags(flags) 1298 , m_instance(instance) 1299 { 1300 } 1301 1302 QtRuntimeMethod::~QtRuntimeMethod() 1303 { 1304 if (m_jsObject) 1305 JSObjectSetPrivate(toRef(m_jsObject.get()), 0); 1306 } 1307 1308 JSValueRef QtRuntimeMethod::call(JSContextRef context, JSObjectRef function, JSObjectRef /*thisObject*/, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) 1309 { 1310 QtRuntimeMethod* d = reinterpret_cast<QtRuntimeMethod*>(JSObjectGetPrivate(function)); 1311 if (!d) { 1312 setException(context, exception, QStringLiteral("cannot call function of deleted runtime method")); 1313 return JSValueMakeUndefined(context); 1314 } 1315 QObject* obj = d->m_object; 1316 1317 if (!obj) { 1318 setException(context, exception, QStringLiteral("cannot call function of deleted QObject")); 1319 return JSValueMakeUndefined(context); 1320 } 1321 1322 // Allow for maximum of 10 arguments and size stack arrays accordingly. 1323 if (argumentCount > 10) 1324 return JSValueMakeUndefined(context); 1325 1326 QVarLengthArray<QVariant, 10> vargs; 1327 void* qargs[11]; 1328 1329 int methodIndex = findMethodIndex(context, obj->metaObject(), d->m_identifier, argumentCount, arguments, 1330 (d->m_flags & AllowPrivate), vargs, (void **)qargs, exception); 1331 1332 if (QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, methodIndex, qargs) >= 0) 1333 return JSValueMakeUndefined(context); 1334 1335 if (vargs.size() > 0 && vargs[0].isValid()) 1336 return toRef(toJS(context), convertQVariantToValue(toJS(context), d->m_instance->rootObject(), vargs[0])); 1337 1338 return JSValueMakeUndefined(context); 1339 } 1340 1341 JSValueRef QtRuntimeMethod::connect(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) 1342 { 1343 return connectOrDisconnect(context, function, thisObject, argumentCount, arguments, exception, true); 1344 } 1345 1346 JSValueRef QtRuntimeMethod::disconnect(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) 1347 { 1348 return connectOrDisconnect(context, function, thisObject, argumentCount, arguments, exception, false); 1349 } 1350 1351 JSObjectRef QtRuntimeMethod::jsObjectRef(JSContextRef context, JSValueRef* exception) 1352 { 1353 if (m_jsObject) 1354 return toRef(m_jsObject.get()); 1355 1356 static const JSClassDefinition classDefForConnect = { 1357 0, 0, "connect", 0, 0, 0, 1358 0, 0, 0, 0, 0, 0, 0, connect, 0, 0, 0 1359 }; 1360 1361 static const JSClassDefinition classDefForDisconnect = { 1362 0, 0, "disconnect", 0, 0, 0, 1363 0, 0, 0, 0, 0, 0, 0, disconnect, 0, 0, 0 1364 }; 1365 1366 static JSClassRef classRefConnect = JSClassCreate(&classDefForConnect); 1367 static JSClassRef classRefDisconnect = JSClassCreate(&classDefForDisconnect); 1368 bool isSignal = m_flags & MethodIsSignal; 1369 JSObjectRef object = JSObjectMake(context, prototypeForSignalsAndSlots(), this); 1370 JSObjectRef connectFunction = JSObjectMake(context, classRefConnect, this); 1371 JSObjectRef disconnectFunction = JSObjectMake(context, classRefDisconnect, this); 1372 JSPropertyAttributes attributes = kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete; 1373 1374 static JSStringRef connectStr = JSStringCreateWithUTF8CString("connect"); 1375 static JSStringRef disconnectStr = JSStringCreateWithUTF8CString("disconnect"); 1376 static JSStringRef lengthStr = JSStringCreateWithUTF8CString("length"); 1377 static JSStringRef nameStr = JSStringCreateWithUTF8CString("name"); 1378 JSRetainPtr<JSStringRef> actualNameStr(Adopt, JSStringCreateWithUTF8CString(m_identifier.constData())); 1379 1380 JSObjectSetProperty(context, connectFunction, lengthStr, JSValueMakeNumber(context, isSignal ? 1 : 0), attributes, exception); 1381 JSObjectSetProperty(context, connectFunction, nameStr, JSValueMakeString(context, connectStr), attributes, exception); 1382 JSObjectSetProperty(context, disconnectFunction, lengthStr, JSValueMakeNumber(context, isSignal ? 1 : 0), attributes, exception); 1383 JSObjectSetProperty(context, disconnectFunction, nameStr, JSValueMakeString(context, disconnectStr), attributes, exception); 1384 1385 JSObjectSetProperty(context, object, connectStr, connectFunction, attributes, exception); 1386 JSObjectSetProperty(context, object, disconnectStr, disconnectFunction, attributes, exception); 1387 JSObjectSetProperty(context, object, lengthStr, JSValueMakeNumber(context, 0), attributes, exception); 1388 JSObjectSetProperty(context, object, nameStr, JSValueMakeString(context, actualNameStr.get()), attributes, exception); 1389 1390 m_jsObject = PassWeak<JSObject>(toJS(object)); 1391 return object; 1392 } 1393 1394 JSValueRef QtRuntimeMethod::connectOrDisconnect(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception, bool connect) 1395 { 1396 QtRuntimeMethod* d = static_cast<QtRuntimeMethod*>(JSObjectGetPrivate(thisObject)); 1397 if (!d) 1398 d = static_cast<QtRuntimeMethod*>(JSObjectGetPrivate(function)); 1399 1400 QString functionName = connect ? QStringLiteral("connect") : QStringLiteral("disconnect"); 1401 1402 if (!argumentCount) { 1403 QString errorStr = QStringLiteral("QtMetaMethod.%1: no arguments given").arg(connect ? QStringLiteral("connect") : QStringLiteral("disconnect")); 1404 setException(context, exception, errorStr); 1405 return JSValueMakeUndefined(context); 1406 } 1407 1408 if ((!(d->m_flags & QtRuntimeMethod::MethodIsSignal))) { 1409 setException(context, exception, QStringLiteral("QtMetaMethod.%3: %1::%2() is not a signal").arg(QString::fromUtf8(d->m_object.data()->metaObject()->className())).arg(QString::fromAscii(d->m_identifier)).arg(functionName)); 1410 return JSValueMakeUndefined(context); 1411 } 1412 1413 QObject* sender = d->m_object.data(); 1414 1415 if (!sender) { 1416 setException(context, exception, QStringLiteral("cannot call function of deleted QObject")); 1417 return JSValueMakeUndefined(context); 1418 } 1419 1420 int signalIndex = findSignalIndex(sender->metaObject(), d->m_index, d->m_identifier); 1421 1422 JSObjectRef targetObject = 0; 1423 JSObjectRef targetFunction = 0; 1424 1425 if (argumentCount == 1) { 1426 if (!JSValueIsObject(context, arguments[0])) { 1427 setException(context, exception, QStringLiteral("QtMetaMethod.%1: target is not a function").arg(functionName)); 1428 return JSValueMakeUndefined(context); 1429 } 1430 targetFunction = JSValueToObject(context, arguments[0], exception); 1431 1432 // object.signal.connect(someFunction); 1433 if (JSObjectIsFunction(context, targetFunction)) { 1434 if (JSValueIsObjectOfClass(context, targetFunction, prototypeForSignalsAndSlots())) { 1435 // object.signal.connect(otherObject.slot); 1436 if (QtRuntimeMethod* targetMethod = static_cast<QtRuntimeMethod*>(JSObjectGetPrivate(targetFunction))) 1437 targetObject = toRef(QtInstance::getQtInstance(targetMethod->m_object.data(), d->m_instance->rootObject(), QtInstance::QtOwnership)->createRuntimeObject(toJS(context))); 1438 } 1439 } else 1440 targetFunction = 0; 1398 1441 } else { 1399 return throwVMError(exec, createError(exec, "cannot call function of deleted QObject")); 1400 } 1401 1402 // void functions return undefined 1403 return JSValue::encode(jsUndefined()); 1404 } 1405 1406 CallType QtRuntimeMetaMethod::getCallData(JSCell*, CallData& callData) 1407 { 1408 callData.native.function = call; 1409 return CallTypeHost; 1410 } 1411 1412 bool QtRuntimeMetaMethod::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot& slot) 1413 { 1414 QtRuntimeMetaMethod* thisObject = jsCast<QtRuntimeMetaMethod*>(cell); 1415 if (propertyName == Identifier(exec, "connect")) { 1416 slot.setCustom(thisObject, thisObject->connectGetter); 1417 return true; 1418 } 1419 if (propertyName == Identifier(exec, "disconnect")) { 1420 slot.setCustom(thisObject, thisObject->disconnectGetter); 1421 return true; 1422 } 1423 if (propertyName == exec->propertyNames().length) { 1424 slot.setCustom(thisObject, thisObject->lengthGetter); 1425 return true; 1426 } 1427 1428 return QtRuntimeMethod::getOwnPropertySlot(thisObject, exec, propertyName, slot); 1429 } 1430 1431 bool QtRuntimeMetaMethod::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor) 1432 { 1433 QtRuntimeMetaMethod* thisObject = jsCast<QtRuntimeMetaMethod*>(object); 1434 if (propertyName == Identifier(exec, "connect")) { 1435 PropertySlot slot; 1436 slot.setCustom(thisObject, connectGetter); 1437 descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly | DontEnum); 1438 return true; 1439 } 1440 1441 if (propertyName == Identifier(exec, "disconnect")) { 1442 PropertySlot slot; 1443 slot.setCustom(thisObject, disconnectGetter); 1444 descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly | DontEnum); 1445 return true; 1446 } 1447 1448 if (propertyName == exec->propertyNames().length) { 1449 PropertySlot slot; 1450 slot.setCustom(thisObject, lengthGetter); 1451 descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly | DontEnum); 1452 return true; 1453 } 1454 1455 return QtRuntimeMethod::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor); 1456 } 1457 1458 void QtRuntimeMetaMethod::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) 1459 { 1460 if (mode == IncludeDontEnumProperties) { 1461 propertyNames.add(Identifier(exec, "connect")); 1462 propertyNames.add(Identifier(exec, "disconnect")); 1463 propertyNames.add(exec->propertyNames().length); 1464 } 1465 1466 QtRuntimeMethod::getOwnPropertyNames(object, exec, propertyNames, mode); 1467 } 1468 1469 JSValue QtRuntimeMetaMethod::lengthGetter(ExecState*, JSValue, PropertyName) 1470 { 1471 // QtScript always returns 0 1472 return jsNumber(0); 1473 } 1474 1475 JSValue QtRuntimeMetaMethod::connectGetter(ExecState* exec, JSValue slotBase, PropertyName ident) 1476 { 1477 QtRuntimeMetaMethod* thisObj = static_cast<QtRuntimeMetaMethod*>(asObject(slotBase)); 1478 QW_DS(QtRuntimeMetaMethod, thisObj); 1479 1480 if (!d->m_connect) 1481 d->m_connect.set(exec->globalData(), thisObj, QtRuntimeConnectionMethod::create(exec, ident.publicName(), true, d->m_instance, d->m_index, d->m_signature)); 1482 return d->m_connect.get(); 1483 } 1484 1485 JSValue QtRuntimeMetaMethod::disconnectGetter(ExecState* exec, JSValue slotBase, PropertyName ident) 1486 { 1487 QtRuntimeMetaMethod* thisObj = static_cast<QtRuntimeMetaMethod*>(asObject(slotBase)); 1488 QW_DS(QtRuntimeMetaMethod, thisObj); 1489 1490 if (!d->m_disconnect) 1491 d->m_disconnect.set(exec->globalData(), thisObj, QtRuntimeConnectionMethod::create(exec, ident.publicName(), false, d->m_instance, d->m_index, d->m_signature)); 1492 return d->m_disconnect.get(); 1442 // object.signal.connect(object, someFunction); 1443 targetObject = JSValueToObject(context, arguments[0], exception); 1444 if (JSValueIsObject(context, arguments[1])) { 1445 JSObjectRef obj = JSValueToObject(context, arguments[1], exception); 1446 if (JSObjectIsFunction(context, obj)) 1447 targetFunction = obj; 1448 } 1449 if (!targetFunction) { 1450 // Maybe the second argument is a string 1451 JSValueRef conversionException = 0; 1452 JSRetainPtr<JSStringRef> functionName(Adopt, JSValueToStringCopy(context, arguments[1], &conversionException)); 1453 if (functionName && !conversionException) { 1454 JSValueRef functionProperty = JSObjectGetProperty(context, targetObject, functionName.get(), &conversionException); 1455 if (!conversionException && functionProperty && JSValueIsObject(context, functionProperty)) { 1456 targetFunction = JSValueToObject(context, functionProperty, 0); 1457 if (!JSObjectIsFunction(context, targetFunction)) 1458 targetFunction = 0; 1459 } 1460 } 1461 } 1462 } 1463 1464 // object.signal.connect(someObject); 1465 if (!targetFunction) { 1466 QString message = QStringLiteral("QtMetaMethod.%1: target is not a function"); 1467 if (connect) 1468 message = message.arg(QStringLiteral("connect")); 1469 else 1470 message = message.arg(QStringLiteral("disconnect")); 1471 setException(context, exception, message); 1472 return JSValueMakeUndefined(context); 1473 } 1474 1475 if (connect) { 1476 // to connect, we need: 1477 // target object [from ctor] 1478 // target signal index etc. [from ctor] 1479 // receiver function [from arguments] 1480 // receiver this object [from arguments] 1481 1482 QtConnectionObject* conn = new QtConnectionObject(context, QtInstance::getQtInstance(sender, d->m_instance->rootObject(), QtInstance::QtOwnership), signalIndex, targetObject, targetFunction); 1483 bool ok = QMetaObject::connect(sender, signalIndex, conn, conn->metaObject()->methodOffset()); 1484 if (!ok) { 1485 delete conn; 1486 QString msg = QString(QLatin1String("QtMetaMethod.connect: failed to connect to %1::%2()")) 1487 .arg(QLatin1String(sender->metaObject()->className())) 1488 .arg(QLatin1String(d->m_identifier)); 1489 setException(context, exception, msg); 1490 return JSValueMakeUndefined(context); 1491 } 1492 1493 // Store connection 1494 QtConnectionObject::connections.insert(sender, conn); 1495 1496 return JSValueMakeUndefined(context); 1497 } 1498 1499 // Now to find our previous connection object. 1500 QList<QtConnectionObject*> conns = QtConnectionObject::connections.values(sender); 1501 1502 foreach (QtConnectionObject* conn, conns) { 1503 // Is this the right connection? 1504 if (!conn->match(context, sender, signalIndex, targetObject, targetFunction)) 1505 continue; 1506 1507 // Yep, disconnect it 1508 QMetaObject::disconnect(sender, signalIndex, conn, conn->metaObject()->methodOffset()); 1509 delete conn; // this will also remove it from the map 1510 return JSValueMakeUndefined(context); 1511 } 1512 1513 QString msg = QStringLiteral("QtMetaMethod.disconnect: failed to disconnect from %1::%2()") 1514 .arg(QLatin1String(sender->metaObject()->className())) 1515 .arg(QLatin1String(d->m_identifier)); 1516 1517 setException(context, exception, msg); 1518 return JSValueMakeUndefined(context); 1493 1519 } 1494 1520 1495 1521 // =============== 1496 1522 1497 QMultiMap<QObject*, QtConnectionObject*> QtRuntimeConnectionMethod::connections; 1498 1499 const ClassInfo QtRuntimeConnectionMethod::s_info = { "QtRuntimeMethod", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(QtRuntimeConnectionMethod) }; 1500 1501 QtRuntimeConnectionMethod::QtRuntimeConnectionMethod(ExecState* exec, Structure* structure, const UString& identifier) 1502 : QtRuntimeMethod (new QtRuntimeConnectionMethodData(), exec, structure, identifier) 1503 { 1504 } 1505 1506 void QtRuntimeConnectionMethod::finishCreation(ExecState* exec, const UString& identifier, bool isConnect, PassRefPtr<QtInstance> instance, int index, const QByteArray& signature) 1507 { 1508 Base::finishCreation(exec, identifier, instance); 1509 QW_D(QtRuntimeConnectionMethod); 1510 1511 d->m_signature = signature; 1512 d->m_index = index; 1513 d->m_isConnect = isConnect; 1514 } 1515 1516 EncodedJSValue QtRuntimeConnectionMethod::call(ExecState* exec) 1517 { 1518 QtRuntimeConnectionMethodData* d = static_cast<QtRuntimeConnectionMethod *>(exec->callee())->d_func(); 1519 1520 JSLockHolder lock(exec); 1521 1522 QObject* sender = d->m_instance->getObject(); 1523 1524 if (sender) { 1525 1526 JSObject* thisObject = exec->lexicalGlobalObject()->methodTable()->toThisObject(exec->lexicalGlobalObject(), exec); 1527 JSObject* funcObject = 0; 1528 1529 // QtScript checks signalness first, arguments second 1530 int signalIndex = -1; 1531 1532 // Make sure the initial index is a signal 1533 QMetaMethod m = sender->metaObject()->method(d->m_index); 1534 if (m.methodType() == QMetaMethod::Signal) 1535 signalIndex = findSignalIndex(sender->metaObject(), d->m_index, d->m_signature); 1536 1537 if (signalIndex != -1) { 1538 if (exec->argumentCount() == 1) { 1539 funcObject = exec->argument(0).toObject(exec); 1540 CallData callData; 1541 if (funcObject->methodTable()->getCallData(funcObject, callData) == CallTypeNone) { 1542 if (d->m_isConnect) 1543 return throwVMError(exec, createTypeError(exec, "QtMetaMethod.connect: target is not a function")); 1544 else 1545 return throwVMError(exec, createTypeError(exec, "QtMetaMethod.disconnect: target is not a function")); 1546 } 1547 } else if (exec->argumentCount() >= 2) { 1548 if (exec->argument(0).isObject()) { 1549 thisObject = exec->argument(0).toObject(exec); 1550 1551 // Get the actual function to call 1552 JSObject *asObj = exec->argument(1).toObject(exec); 1553 CallData callData; 1554 if (asObj->methodTable()->getCallData(asObj, callData) != CallTypeNone) { 1555 // Function version 1556 funcObject = asObj; 1557 } else { 1558 // Convert it to a string 1559 UString funcName = exec->argument(1).toString(exec)->value(exec); 1560 Identifier funcIdent(exec, funcName); 1561 1562 // ### DropAllLocks 1563 // This is resolved at this point in QtScript 1564 JSValue val = thisObject->get(exec, funcIdent); 1565 JSObject* asFuncObj = val.toObject(exec); 1566 1567 if (asFuncObj->methodTable()->getCallData(asFuncObj, callData) != CallTypeNone) { 1568 funcObject = asFuncObj; 1569 } else { 1570 if (d->m_isConnect) 1571 return throwVMError(exec, createTypeError(exec, "QtMetaMethod.connect: target is not a function")); 1572 else 1573 return throwVMError(exec, createTypeError(exec, "QtMetaMethod.disconnect: target is not a function")); 1574 } 1575 } 1576 } else { 1577 if (d->m_isConnect) 1578 return throwVMError(exec, createTypeError(exec, "QtMetaMethod.connect: thisObject is not an object")); 1579 else 1580 return throwVMError(exec, createTypeError(exec, "QtMetaMethod.disconnect: thisObject is not an object")); 1581 } 1582 } else { 1583 if (d->m_isConnect) 1584 return throwVMError(exec, createError(exec, "QtMetaMethod.connect: no arguments given")); 1585 else 1586 return throwVMError(exec, createError(exec, "QtMetaMethod.disconnect: no arguments given")); 1587 } 1588 1589 if (d->m_isConnect) { 1590 // to connect, we need: 1591 // target object [from ctor] 1592 // target signal index etc. [from ctor] 1593 // receiver function [from arguments] 1594 // receiver this object [from arguments] 1595 1596 QtConnectionObject* conn = QtConnectionObject::createWithInternalJSC(exec, d->m_instance, signalIndex, thisObject, funcObject); 1597 bool ok = QMetaObject::connect(sender, signalIndex, conn, conn->metaObject()->methodOffset()); 1598 if (!ok) { 1599 delete conn; 1600 QString msg = QString(QLatin1String("QtMetaMethod.connect: failed to connect to %1::%2()")) 1601 .arg(QLatin1String(sender->metaObject()->className())) 1602 .arg(QLatin1String(d->m_signature)); 1603 return throwVMError(exec, createError(exec, msg.toLatin1().constData())); 1604 } 1605 else { 1606 // Store connection 1607 connections.insert(sender, conn); 1608 } 1609 } else { 1610 // Now to find our previous connection object. Hmm. 1611 QList<QtConnectionObject*> conns = connections.values(sender); 1612 bool ret = false; 1613 1614 JSContextRef context = ::toRef(exec); 1615 JSObjectRef receiver = ::toRef(thisObject); 1616 JSObjectRef receiverFunction = ::toRef(funcObject); 1617 1618 foreach(QtConnectionObject* conn, conns) { 1619 // Is this the right connection? 1620 if (conn->match(context, sender, signalIndex, receiver, receiverFunction)) { 1621 // Yep, disconnect it 1622 QMetaObject::disconnect(sender, signalIndex, conn, conn->metaObject()->methodOffset()); 1623 delete conn; // this will also remove it from the map 1624 ret = true; 1625 break; 1626 } 1627 } 1628 1629 if (!ret) { 1630 QString msg = QString(QLatin1String("QtMetaMethod.disconnect: failed to disconnect from %1::%2()")) 1631 .arg(QLatin1String(sender->metaObject()->className())) 1632 .arg(QLatin1String(d->m_signature)); 1633 return throwVMError(exec, createError(exec, msg.toLatin1().constData())); 1634 } 1635 } 1636 } else { 1637 QString msg = QString(QLatin1String("QtMetaMethod.%1: %2::%3() is not a signal")) 1638 .arg(QLatin1String(d->m_isConnect ? "connect": "disconnect")) 1639 .arg(QLatin1String(sender->metaObject()->className())) 1640 .arg(QLatin1String(d->m_signature)); 1641 return throwVMError(exec, createTypeError(exec, msg.toLatin1().constData())); 1642 } 1643 } else { 1644 return throwVMError(exec, createError(exec, "cannot call function of deleted QObject")); 1645 } 1646 1647 return JSValue::encode(jsUndefined()); 1648 } 1649 1650 CallType QtRuntimeConnectionMethod::getCallData(JSCell*, CallData& callData) 1651 { 1652 callData.native.function = call; 1653 return CallTypeHost; 1654 } 1655 1656 bool QtRuntimeConnectionMethod::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot& slot) 1657 { 1658 QtRuntimeConnectionMethod* thisObject = jsCast<QtRuntimeConnectionMethod*>(cell); 1659 if (propertyName == exec->propertyNames().length) { 1660 slot.setCustom(thisObject, thisObject->lengthGetter); 1661 return true; 1662 } 1663 1664 return QtRuntimeMethod::getOwnPropertySlot(thisObject, exec, propertyName, slot); 1665 } 1666 1667 bool QtRuntimeConnectionMethod::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor) 1668 { 1669 QtRuntimeConnectionMethod* thisObject = jsCast<QtRuntimeConnectionMethod*>(object); 1670 if (propertyName == exec->propertyNames().length) { 1671 PropertySlot slot; 1672 slot.setCustom(thisObject, lengthGetter); 1673 descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly | DontEnum); 1674 return true; 1675 } 1676 1677 return QtRuntimeMethod::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor); 1678 } 1679 1680 void QtRuntimeConnectionMethod::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) 1681 { 1682 if (mode == IncludeDontEnumProperties) 1683 propertyNames.add(exec->propertyNames().length); 1684 1685 QtRuntimeMethod::getOwnPropertyNames(object, exec, propertyNames, mode); 1686 } 1687 1688 JSValue QtRuntimeConnectionMethod::lengthGetter(ExecState*, JSValue, PropertyName) 1689 { 1690 // we have one formal argument, and one optional 1691 return jsNumber(1); 1692 } 1693 1694 // =============== 1523 QMultiMap<QObject*, QtConnectionObject*> QtConnectionObject::connections; 1695 1524 1696 1525 QtConnectionObject::QtConnectionObject(JSContextRef context, PassRefPtr<QtInstance> senderInstance, int signalIndex, JSObjectRef receiver, JSObjectRef receiverFunction) … … 1712 1541 // We can safely use m_originalSender because connection object will never outlive the sender, 1713 1542 // which is its QObject parent. 1714 QtRuntimeConnectionMethod::connections.remove(m_originalSender, this);1543 connections.remove(m_originalSender, this); 1715 1544 1716 1545 if (m_receiver) … … 1846 1675 } 1847 1676 1848 QtConnectionObject* QtConnectionObject::createWithInternalJSC(ExecState* exec, PassRefPtr<QtInstance> senderInstance, int signalIndex, JSObject* receiver, JSObject* receiverFunction)1849 {1850 return new QtConnectionObject(::toRef(exec), senderInstance, signalIndex, ::toRef(receiver), ::toRef(receiverFunction));1851 }1852 1853 1677 // =============== 1854 1678 -
trunk/Source/WebCore/bridge/qt/qt_runtime.h
r125032 r125428 96 96 }; 97 97 98 // Based on RuntimeMethod 98 class QtRuntimeMethod { 99 public: 100 enum MethodFlags { 101 MethodIsSignal = 1, 102 AllowPrivate = 2 103 }; 99 104 100 // Extra data classes (to avoid the CELL_SIZE limit on JS objects) 101 class QtRuntimeMethod; 102 class QtRuntimeMethodData : public WeakHandleOwner { 103 public: 104 virtual ~QtRuntimeMethodData(); 105 RefPtr<QtInstance> m_instance; 106 Weak<QtRuntimeMethod> m_finalizer; 105 QtRuntimeMethod(JSContextRef, JSValueRef* exception, QObject*, const QByteArray& identifier, int signalIndex, int flags, QtInstance*); 106 ~QtRuntimeMethod(); 107 107 108 private:109 void finalize(Handle<Unknown>, void*);110 };108 static JSValueRef call(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception); 109 static JSValueRef connect(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception); 110 static JSValueRef disconnect(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception); 111 111 112 class QtRuntimeConnectionMethod; 113 class QtRuntimeMetaMethodData : public QtRuntimeMethodData { 114 public: 115 ~QtRuntimeMetaMethodData(); 116 QByteArray m_signature; 117 bool m_allowPrivate; 118 int m_index; 119 WriteBarrier<QtRuntimeConnectionMethod> m_connect; 120 WriteBarrier<QtRuntimeConnectionMethod> m_disconnect; 121 }; 112 JSObjectRef jsObjectRef(JSContextRef, JSValueRef* exception); 122 113 123 class QtRuntimeConnectionMethodData : public QtRuntimeMethodData { 124 public: 125 ~QtRuntimeConnectionMethodData(); 126 QByteArray m_signature; 127 int m_index; 128 bool m_isConnect; 129 }; 130 131 // Common base class (doesn't really do anything interesting) 132 class QtRuntimeMethod : public InternalFunction { 133 public: 134 typedef InternalFunction Base; 135 136 ~QtRuntimeMethod(); 137 static void destroy(JSCell*); 138 139 static const ClassInfo s_info; 140 141 static FunctionPrototype* createPrototype(ExecState*, JSGlobalObject* globalObject) 142 { 143 return globalObject->functionPrototype(); 144 } 145 146 static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) 147 { 148 return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); 149 } 150 151 protected: 152 void finishCreation(ExecState*, const UString&, PassRefPtr<QtInstance>); 153 static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | InternalFunction::StructureFlags | OverridesVisitChildren; 154 155 QtRuntimeMethodData *d_func() const {return d_ptr;} 156 QtRuntimeMethod(QtRuntimeMethodData *dd, ExecState *, Structure*, const UString& name); 157 QtRuntimeMethodData *d_ptr; 158 }; 159 160 class QtRuntimeMetaMethod : public QtRuntimeMethod { 161 public: 162 typedef QtRuntimeMethod Base; 163 164 static QtRuntimeMetaMethod* create(ExecState* exec, const UString& name, PassRefPtr<QtInstance> instance, int index, const QByteArray& signature, bool allowPrivate) 165 { 166 Structure* domStructure = WebCore::deprecatedGetDOMStructure<QtRuntimeMetaMethod>(exec); 167 QtRuntimeMetaMethod* method = new (allocateCell<QtRuntimeMetaMethod>(*exec->heap())) QtRuntimeMetaMethod(exec, domStructure, name); 168 method->finishCreation(exec, name, instance, index, signature, allowPrivate); 169 return method; 170 } 171 172 static bool getOwnPropertySlot(JSCell*, ExecState *, PropertyName, PropertySlot&); 173 static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&); 174 static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); 175 176 static void visitChildren(JSCell*, SlotVisitor&); 177 178 static const ClassInfo s_info; 179 180 static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) 181 { 182 return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); 183 } 184 185 protected: 186 QtRuntimeMetaMethodData* d_func() const {return reinterpret_cast<QtRuntimeMetaMethodData*>(d_ptr);} 114 const QByteArray& name() { return m_identifier; } 187 115 188 116 private: 189 QtRuntimeMetaMethod(ExecState*, Structure*, const UString&);190 void finishCreation(ExecState*, const UString&, PassRefPtr<QtInstance>, int index, const QByteArray& signature, bool allowPrivate);117 static const JSStaticFunction connectFunction; 118 static const JSStaticFunction disconnectFunction; 191 119 192 static CallType getCallData(JSCell*, CallData&); 193 static EncodedJSValue JSC_HOST_CALL call(ExecState* exec); 194 static JSValue lengthGetter(ExecState*, JSValue, PropertyName); 195 static JSValue connectGetter(ExecState*, JSValue, PropertyName); 196 static JSValue disconnectGetter(ExecState*, JSValue, PropertyName); 197 }; 198 199 class QtConnectionObject; 200 class QtRuntimeConnectionMethod : public QtRuntimeMethod { 201 public: 202 typedef QtRuntimeMethod Base; 203 204 static QtRuntimeConnectionMethod* create(ExecState* exec, const UString& name, bool isConnect, PassRefPtr<QtInstance> instance, int index, const QByteArray& signature) 205 { 206 Structure* domStructure = WebCore::deprecatedGetDOMStructure<QtRuntimeConnectionMethod>(exec); 207 QtRuntimeConnectionMethod* method = new (allocateCell<QtRuntimeConnectionMethod>(*exec->heap())) QtRuntimeConnectionMethod(exec, domStructure, name); 208 method->finishCreation(exec, name, isConnect, instance, index, signature); 209 return method; 210 } 211 212 static bool getOwnPropertySlot(JSCell*, ExecState *, PropertyName, PropertySlot&); 213 static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&); 214 static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); 215 216 static const ClassInfo s_info; 217 218 static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) 219 { 220 return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); 221 } 222 223 protected: 224 QtRuntimeConnectionMethodData* d_func() const {return reinterpret_cast<QtRuntimeConnectionMethodData*>(d_ptr);} 225 226 private: 227 QtRuntimeConnectionMethod(ExecState*, Structure*, const UString&); 228 void finishCreation(ExecState*, const UString&, bool isConnect, PassRefPtr<QtInstance>, int index, const QByteArray& signature); 229 230 static CallType getCallData(JSCell*, CallData&); 231 static EncodedJSValue JSC_HOST_CALL call(ExecState* exec); 232 static JSValue lengthGetter(ExecState*, JSValue, PropertyName); 233 static QMultiMap<QObject *, QtConnectionObject *> connections; 234 friend class QtConnectionObject; 120 static JSValueRef connectOrDisconnect(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception, bool connect); 121 QPointer<QObject> m_object; 122 QByteArray m_identifier; 123 int m_index; 124 int m_flags; 125 Weak<JSObject> m_jsObject; 126 QtInstance* m_instance; 235 127 }; 236 128 … … 248 140 bool match(JSContextRef, QObject* sender, int signalIndex, JSObjectRef thisObject, JSObjectRef funcObject); 249 141 250 // Note: for callers using JSC internals, remove once we don't need anymore.251 static QtConnectionObject* createWithInternalJSC(ExecState*, PassRefPtr<QtInstance> senderInstance, int signalIndex, JSObject* receiver, JSObject* receiverFunction);252 253 142 private: 254 143 JSGlobalContextRef m_context; … … 261 150 JSObjectRef m_receiver; 262 151 JSObjectRef m_receiverFunction; 152 153 friend class QtRuntimeMethod; 154 static QMultiMap<QObject*, QtConnectionObject*> connections; 263 155 }; 264 156 -
trunk/Source/WebKit/qt/ChangeLog
r125411 r125428 1 2012-08-13 Simon Hausmann <simon.hausmann@nokia.com> 2 3 [Qt] Port meta method/signal/slot handling in run-time bridge to use JSC C API 4 https://bugs.webkit.org/show_bug.cgi?id=93476 5 6 Reviewed by Kenneth Rohde Christiansen. 7 8 Changed semantics of some test expectations. Similarly to r125032 when generating 9 error exceptions for connect/disconnect, we cannot generate explicit type error 10 exceptions but only generic errors. Another change is that the meta-method wrapper 11 doesn't support the call() through Function.prototype anymore. See WebCore changelog 12 for details. 13 14 * tests/qobjectbridge/tst_qobjectbridge.cpp: 15 (tst_QObjectBridge::connectAndDisconnect): 16 (tst_QObjectBridge::objectDeleted): 17 (tst_QObjectBridge::introspectQtMethods): 18 1 19 2012-08-13 Kwang Yul Seo <skyul@company100.net> 2 20 -
trunk/Source/WebKit/qt/tests/qobjectbridge/tst_qobjectbridge.cpp
r125275 r125428 1500 1500 1501 1501 // connect(obj, string) 1502 QCOMPARE(evalJS("myObject.mySignal.connect(yetAnotherObject, 'func')"), sUndefined); 1503 QCOMPARE(evalJS("myObject.mySignal.connect(myObject, 'mySlot')"), sUndefined); 1504 QCOMPARE(evalJS("myObject.mySignal.disconnect(yetAnotherObject, 'func')"), sUndefined); 1505 QCOMPARE(evalJS("myObject.mySignal.disconnect(myObject, 'mySlot')"), sUndefined); 1502 { 1503 QString type; 1504 QCOMPARE(evalJS("myObject.mySignal.connect(yetAnotherObject, 'func')", type), sUndefined); 1505 QCOMPARE(evalJS("myObject.mySignal.connect(myObject, 'mySlot')", type), sUndefined); 1506 QCOMPARE(evalJS("myObject.mySignal.disconnect(yetAnotherObject, 'func')", type), sUndefined); 1507 QCOMPARE(evalJS("myObject.mySignal.disconnect(myObject, 'mySlot')", type), sUndefined); 1508 } 1506 1509 1507 1510 // check that emitting signals from script works … … 1556 1559 QCOMPARE(evalJS("myObject.mySignalWithIntArg.disconnect(myObject['myOverloadedSlot(int)'])"), sUndefined); 1557 1560 1561 QCOMPARE(evalJS("myObject.mySignalWithIntArg.connect(myObject, 'myOverloadedSlot(int)')"), sUndefined); 1562 m_myObject->resetQtFunctionInvoked(); 1563 QCOMPARE(evalJS("myObject.mySignalWithIntArg(456)"), sUndefined); 1564 QCOMPARE(m_myObject->qtFunctionInvoked(), 28); // int overload 1565 QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); 1566 QCOMPARE(m_myObject->qtFunctionActuals().at(0).toInt(), 456); 1567 QCOMPARE(evalJS("myObject.mySignalWithIntArg.disconnect(myObject, 'myOverloadedSlot(int)')"), sUndefined); 1568 1558 1569 // erroneous input 1559 1570 { … … 1588 1599 QString ret = evalJS("myObject.myInvokable.connect(123)", type); 1589 1600 QCOMPARE(type, sError); 1590 QCOMPARE(ret, QLatin1String(" TypeError: QtMetaMethod.connect: MyQObject::myInvokable() is not a signal"));1601 QCOMPARE(ret, QLatin1String("Error: QtMetaMethod.connect: MyQObject::myInvokable() is not a signal")); 1591 1602 } 1592 1603 { … … 1594 1605 QString ret = evalJS("myObject.myInvokable.connect(function() { })", type); 1595 1606 QCOMPARE(type, sError); 1596 QCOMPARE(ret, QLatin1String(" TypeError: QtMetaMethod.connect: MyQObject::myInvokable() is not a signal"));1607 QCOMPARE(ret, QLatin1String("Error: QtMetaMethod.connect: MyQObject::myInvokable() is not a signal")); 1597 1608 } 1598 1609 … … 1601 1612 QString ret = evalJS("myObject.mySignal.connect(123)", type); 1602 1613 QCOMPARE(type, sError); 1603 QCOMPARE(ret, QLatin1String("TypeError: QtMetaMethod.connect: target is not a function")); 1614 QCOMPARE(ret, QLatin1String("Error: QtMetaMethod.connect: target is not a function")); 1615 } 1616 1617 { 1618 QString type; 1619 QString ret = evalJS("var randomObject = new Object; myObject.mySignal.connect(myObject, randomObject)", type); 1620 QCOMPARE(type, sError); 1621 QCOMPARE(ret, QLatin1String("Error: QtMetaMethod.connect: target is not a function")); 1622 } 1623 1624 { 1625 QString type; 1626 QString ret = evalJS("myObject.mySignal.connect(myObject, 'nonExistantSlot')", type); 1627 QCOMPARE(type, sError); 1628 QCOMPARE(ret, QLatin1String("Error: QtMetaMethod.connect: target is not a function")); 1604 1629 } 1605 1630 … … 1617 1642 } 1618 1643 1644 { 1645 QString type; 1646 QString ret = evalJS("myObject.mySignal.disconnect(myObject, 'nonExistantSlot')", type); 1647 QCOMPARE(type, sError); 1648 QCOMPARE(ret, QLatin1String("Error: QtMetaMethod.disconnect: target is not a function")); 1649 } 1650 1619 1651 /* XFAIL - Function.prototype doesn't get connect/disconnect, just signals/slots 1620 1652 { … … 1630 1662 QString ret = evalJS("var o = { }; o.disconnect = myObject.myInvokable.disconnect; o.disconnect(123)", type); 1631 1663 QCOMPARE(type, sError); 1632 QCOMPARE(ret, QLatin1String(" TypeError: QtMetaMethod.disconnect: MyQObject::myInvokable() is not a signal"));1664 QCOMPARE(ret, QLatin1String("Error: QtMetaMethod.disconnect: MyQObject::myInvokable() is not a signal")); 1633 1665 } 1634 1666 … … 1637 1669 QString ret = evalJS("myObject.myInvokable.disconnect(123)", type); 1638 1670 QCOMPARE(type, sError); 1639 QCOMPARE(ret, QLatin1String(" TypeError: QtMetaMethod.disconnect: MyQObject::myInvokable() is not a signal"));1671 QCOMPARE(ret, QLatin1String("Error: QtMetaMethod.disconnect: MyQObject::myInvokable() is not a signal")); 1640 1672 } 1641 1673 { … … 1643 1675 QString ret = evalJS("myObject.myInvokable.disconnect(function() { })", type); 1644 1676 QCOMPARE(type, sError); 1645 QCOMPARE(ret, QLatin1String(" TypeError: QtMetaMethod.disconnect: MyQObject::myInvokable() is not a signal"));1677 QCOMPARE(ret, QLatin1String("Error: QtMetaMethod.disconnect: MyQObject::myInvokable() is not a signal")); 1646 1678 } 1647 1679 … … 1650 1682 QString ret = evalJS("myObject.mySignal.disconnect(123)", type); 1651 1683 QCOMPARE(type, sError); 1652 QCOMPARE(ret, QLatin1String(" TypeError: QtMetaMethod.disconnect: target is not a function"));1684 QCOMPARE(ret, QLatin1String("Error: QtMetaMethod.disconnect: target is not a function")); 1653 1685 } 1654 1686 … … 1848 1880 QCOMPARE(qobj->intProperty(), 123); 1849 1881 qobj->resetQtFunctionInvoked(); 1850 evalJS("bar.myInvokable .call(bar);");1882 evalJS("bar.myInvokable(bar);"); 1851 1883 QCOMPARE(qobj->qtFunctionInvoked(), 0); 1852 1884 … … 2146 2178 QCOMPARE(evalJS(QString::fromLatin1("descriptor.value === %0['%1']").arg(methodLookup).arg(name)), sTrue); 2147 2179 QCOMPARE(evalJS(QString::fromLatin1("descriptor.enumerable")), sFalse); 2148 QCOMPARE(evalJS(QString::fromLatin1("descriptor.configurable")), s False);2180 QCOMPARE(evalJS(QString::fromLatin1("descriptor.configurable")), sTrue); 2149 2181 } 2150 2182
Note: See TracChangeset
for help on using the changeset viewer.