976 Q_ASSERT(data->object.inherits(&QScriptObject::info)); |
976 Q_ASSERT(data->object.inherits(&QScriptObject::info)); |
977 QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(data->object)); |
977 QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(data->object)); |
978 QScriptObjectDelegate *delegate = scriptObject->delegate(); |
978 QScriptObjectDelegate *delegate = scriptObject->delegate(); |
979 Q_ASSERT(delegate && (delegate->type() == QScriptObjectDelegate::QtObject)); |
979 Q_ASSERT(delegate && (delegate->type() == QScriptObjectDelegate::QtObject)); |
980 QObject *qobj = static_cast<QScript::QObjectDelegate*>(delegate)->value(); |
980 QObject *qobj = static_cast<QScript::QObjectDelegate*>(delegate)->value(); |
981 Q_ASSERT_X(qobj != 0, "QtFunction::call", "handle the case when QObject has been deleted"); |
981 if (!qobj) |
|
982 return JSC::throwError(exec, JSC::GeneralError, QString::fromLatin1("cannot call function of deleted QObject")); |
982 QScriptEnginePrivate *engine = scriptEngineFromExec(exec); |
983 QScriptEnginePrivate *engine = scriptEngineFromExec(exec); |
983 |
984 |
984 const QMetaObject *meta = qobj->metaObject(); |
985 const QMetaObject *meta = qobj->metaObject(); |
985 QObject *thisQObject = 0; |
986 QObject *thisQObject = 0; |
986 thisValue = engine->toUsableValue(thisValue); |
987 thisValue = engine->toUsableValue(thisValue); |
1278 } |
1280 } |
1279 } |
1281 } |
1280 } |
1282 } |
1281 |
1283 |
1282 return QScriptObjectDelegate::getOwnPropertySlot(object, exec, propertyName, slot); |
1284 return QScriptObjectDelegate::getOwnPropertySlot(object, exec, propertyName, slot); |
|
1285 #else //QT_NO_PROPERTIES |
|
1286 return false; |
|
1287 #endif //QT_NO_PROPERTIES |
|
1288 } |
|
1289 |
|
1290 |
|
1291 bool QObjectDelegate::getOwnPropertyDescriptor(QScriptObject *object, JSC::ExecState *exec, |
|
1292 const JSC::Identifier &propertyName, |
|
1293 JSC::PropertyDescriptor &descriptor) |
|
1294 { |
|
1295 //Note: this has to be kept in sync with getOwnPropertySlot abd getPropertyAttributes |
|
1296 #ifndef QT_NO_PROPERTIES |
|
1297 QByteArray name = QString(propertyName.ustring()).toLatin1(); |
|
1298 QObject *qobject = data->value; |
|
1299 if (!qobject) { |
|
1300 QString message = QString::fromLatin1("cannot access member `%0' of deleted QObject") |
|
1301 .arg(QString::fromLatin1(name)); |
|
1302 descriptor.setValue(JSC::throwError(exec, JSC::GeneralError, message)); |
|
1303 return true; |
|
1304 } |
|
1305 |
|
1306 const QScriptEngine::QObjectWrapOptions &opt = data->options; |
|
1307 |
|
1308 const QMetaObject *meta = qobject->metaObject(); |
|
1309 { |
|
1310 QHash<QByteArray, JSC::JSValue>::const_iterator it = data->cachedMembers.constFind(name); |
|
1311 if (it != data->cachedMembers.constEnd()) { |
|
1312 int index; |
|
1313 if (GeneratePropertyFunctions && ((index = meta->indexOfProperty(name)) != -1)) { |
|
1314 QMetaProperty prop = meta->property(index); |
|
1315 descriptor.setAccessorDescriptor(it.value(), it.value(), flagsForMetaProperty(prop)); |
|
1316 if (!prop.isWritable()) |
|
1317 descriptor.setWritable(false); |
|
1318 } else { |
|
1319 unsigned attributes = QObjectMemberAttribute; |
|
1320 if (opt & QScriptEngine::SkipMethodsInEnumeration) |
|
1321 attributes |= JSC::DontEnum; |
|
1322 descriptor.setDescriptor(it.value(), attributes); |
|
1323 } |
|
1324 return true; |
|
1325 } |
|
1326 } |
|
1327 |
|
1328 QScriptEnginePrivate *eng = scriptEngineFromExec(exec); |
|
1329 int index = -1; |
|
1330 if (name.contains('(')) { |
|
1331 QByteArray normalized = QMetaObject::normalizedSignature(name); |
|
1332 if (-1 != (index = meta->indexOfMethod(normalized))) { |
|
1333 QMetaMethod method = meta->method(index); |
|
1334 if (hasMethodAccess(method, index, opt)) { |
|
1335 if (!(opt & QScriptEngine::ExcludeSuperClassMethods) |
|
1336 || (index >= meta->methodOffset())) { |
|
1337 QtFunction *fun = new (exec)QtFunction( |
|
1338 object, index, /*maybeOverloaded=*/false, |
|
1339 &exec->globalData(), eng->originalGlobalObject()->functionStructure(), |
|
1340 propertyName); |
|
1341 data->cachedMembers.insert(name, fun); |
|
1342 unsigned attributes = QObjectMemberAttribute; |
|
1343 if (opt & QScriptEngine::SkipMethodsInEnumeration) |
|
1344 attributes |= JSC::DontEnum; |
|
1345 descriptor.setDescriptor(fun, attributes); |
|
1346 return true; |
|
1347 } |
|
1348 } |
|
1349 } |
|
1350 } |
|
1351 |
|
1352 index = meta->indexOfProperty(name); |
|
1353 if (index != -1) { |
|
1354 QMetaProperty prop = meta->property(index); |
|
1355 if (prop.isScriptable()) { |
|
1356 if (!(opt & QScriptEngine::ExcludeSuperClassProperties) |
|
1357 || (index >= meta->propertyOffset())) { |
|
1358 unsigned attributes = flagsForMetaProperty(prop); |
|
1359 if (GeneratePropertyFunctions) { |
|
1360 QtPropertyFunction *fun = new (exec)QtPropertyFunction( |
|
1361 meta, index, &exec->globalData(), |
|
1362 eng->originalGlobalObject()->functionStructure(), |
|
1363 propertyName); |
|
1364 data->cachedMembers.insert(name, fun); |
|
1365 descriptor.setAccessorDescriptor(fun, fun, attributes); |
|
1366 if (attributes & JSC::ReadOnly) |
|
1367 descriptor.setWritable(false); |
|
1368 } else { |
|
1369 JSC::JSValue val; |
|
1370 if (!prop.isValid()) |
|
1371 val = JSC::jsUndefined(); |
|
1372 else |
|
1373 val = eng->jscValueFromVariant(prop.read(qobject)); |
|
1374 descriptor.setDescriptor(val, attributes); |
|
1375 } |
|
1376 return true; |
|
1377 } |
|
1378 } |
|
1379 } |
|
1380 |
|
1381 index = qobject->dynamicPropertyNames().indexOf(name); |
|
1382 if (index != -1) { |
|
1383 JSC::JSValue val = eng->jscValueFromVariant(qobject->property(name)); |
|
1384 descriptor.setDescriptor(val, QObjectMemberAttribute); |
|
1385 return true; |
|
1386 } |
|
1387 |
|
1388 const int offset = (opt & QScriptEngine::ExcludeSuperClassMethods) |
|
1389 ? meta->methodOffset() : 0; |
|
1390 for (index = meta->methodCount() - 1; index >= offset; --index) { |
|
1391 QMetaMethod method = meta->method(index); |
|
1392 if (hasMethodAccess(method, index, opt) |
|
1393 && (methodName(method) == name)) { |
|
1394 QtFunction *fun = new (exec)QtFunction( |
|
1395 object, index, /*maybeOverloaded=*/true, |
|
1396 &exec->globalData(), eng->originalGlobalObject()->functionStructure(), |
|
1397 propertyName); |
|
1398 unsigned attributes = QObjectMemberAttribute; |
|
1399 if (opt & QScriptEngine::SkipMethodsInEnumeration) |
|
1400 attributes |= JSC::DontEnum; |
|
1401 descriptor.setDescriptor(fun, attributes); |
|
1402 data->cachedMembers.insert(name, fun); |
|
1403 return true; |
|
1404 } |
|
1405 } |
|
1406 |
|
1407 if (!(opt & QScriptEngine::ExcludeChildObjects)) { |
|
1408 QList<QObject*> children = qobject->children(); |
|
1409 for (index = 0; index < children.count(); ++index) { |
|
1410 QObject *child = children.at(index); |
|
1411 if (child->objectName() == QString(propertyName.ustring())) { |
|
1412 QScriptEngine::QObjectWrapOptions opt = QScriptEngine::PreferExistingWrapperObject; |
|
1413 QScriptValue tmp = QScriptEnginePrivate::get(eng)->newQObject(child, QScriptEngine::QtOwnership, opt); |
|
1414 descriptor.setDescriptor(eng->scriptValueToJSCValue(tmp), JSC::ReadOnly | JSC::DontDelete | JSC::DontEnum); |
|
1415 return true; |
|
1416 } |
|
1417 } |
|
1418 } |
|
1419 |
|
1420 return QScriptObjectDelegate::getOwnPropertyDescriptor(object, exec, propertyName, descriptor); |
1283 #else //QT_NO_PROPERTIES |
1421 #else //QT_NO_PROPERTIES |
1284 return false; |
1422 return false; |
1285 #endif //QT_NO_PROPERTIES |
1423 #endif //QT_NO_PROPERTIES |
1286 } |
1424 } |
1287 |
1425 |
1686 | QScriptEngine::ExcludeChildObjects)); |
1824 | QScriptEngine::ExcludeChildObjects)); |
1687 |
1825 |
1688 putDirectFunction(exec, new (exec) JSC::PrototypeFunction(exec, prototypeFunctionStructure, /*length=*/0, exec->propertyNames().toString, qobjectProtoFuncToString), JSC::DontEnum); |
1826 putDirectFunction(exec, new (exec) JSC::PrototypeFunction(exec, prototypeFunctionStructure, /*length=*/0, exec->propertyNames().toString, qobjectProtoFuncToString), JSC::DontEnum); |
1689 putDirectFunction(exec, new (exec) JSC::PrototypeFunction(exec, prototypeFunctionStructure, /*length=*/1, JSC::Identifier(exec, "findChild"), qobjectProtoFuncFindChild), JSC::DontEnum); |
1827 putDirectFunction(exec, new (exec) JSC::PrototypeFunction(exec, prototypeFunctionStructure, /*length=*/1, JSC::Identifier(exec, "findChild"), qobjectProtoFuncFindChild), JSC::DontEnum); |
1690 putDirectFunction(exec, new (exec) JSC::PrototypeFunction(exec, prototypeFunctionStructure, /*length=*/1, JSC::Identifier(exec, "findChildren"), qobjectProtoFuncFindChildren), JSC::DontEnum); |
1828 putDirectFunction(exec, new (exec) JSC::PrototypeFunction(exec, prototypeFunctionStructure, /*length=*/1, JSC::Identifier(exec, "findChildren"), qobjectProtoFuncFindChildren), JSC::DontEnum); |
|
1829 this->structure()->setHasGetterSetterProperties(true); |
1691 } |
1830 } |
1692 |
1831 |
1693 const JSC::ClassInfo QMetaObjectWrapperObject::info = { "QMetaObject", 0, 0, 0 }; |
1832 const JSC::ClassInfo QMetaObjectWrapperObject::info = { "QMetaObject", 0, 0, 0 }; |
1694 |
1833 |
1695 QMetaObjectWrapperObject::QMetaObjectWrapperObject( |
1834 QMetaObjectWrapperObject::QMetaObjectWrapperObject( |
2079 if (exec->hadException()) |
2218 if (exec->hadException()) |
2080 exec->clearException(); // ### otherwise JSC asserts |
2219 exec->clearException(); // ### otherwise JSC asserts |
2081 JSC::call(exec, slot, callType, callData, thisObject, jscArgs); |
2220 JSC::call(exec, slot, callType, callData, thisObject, jscArgs); |
2082 |
2221 |
2083 if (exec->hadException()) { |
2222 if (exec->hadException()) { |
2084 engine->emitSignalHandlerException(); |
2223 if (slot.inherits(&QtFunction::info) && !static_cast<QtFunction*>(JSC::asObject(slot))->qobject()) { |
|
2224 // The function threw an error because the target QObject has been deleted. |
|
2225 // The connections list is stale; remove the signal handler and ignore the exception. |
|
2226 removeSignalHandler(sender(), signalIndex, receiver, slot); |
|
2227 exec->clearException(); |
|
2228 } else { |
|
2229 engine->emitSignalHandlerException(); |
|
2230 } |
2085 } |
2231 } |
2086 } |
2232 } |
2087 |
2233 |
2088 QObjectConnectionManager::QObjectConnectionManager(QScriptEnginePrivate *eng) |
2234 QObjectConnectionManager::QObjectConnectionManager(QScriptEnginePrivate *eng) |
2089 : engine(eng), slotCounter(0) |
2235 : engine(eng), slotCounter(0) |