QtQml: Key singletons by singleton instance info
We can keep the singleton instance info the same across multiple types created in a single registration call. The result is that we only get one singleton instance per engine, rather than separate ones for each version. If you invoke qmlRegisterSingletonType separately, you still get separate instances, though. [ChangeLog][QtQml][Important Behavior Changes] The QML engine will now refrain from creating separate instances of a singleton type for each version it is registered for if the singleton is registered declaratively (using QML_SINGLETON). The behavior of procedurally registered singletons (using the qmlRegisterSingletonType() family of functions) remains the same: For each registration call, a separate singleton instance is created. Task-number: QTBUG-116432 Change-Id: Ic8a5de0f88ef530670cfd81b192201a8ab49b2f7 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
041b326fe6
commit
4cdf0643b4
|
@ -79,8 +79,20 @@ public:
|
|||
|
||||
inline T* take() { T *res = o; o = nullptr; return res; }
|
||||
|
||||
friend bool operator==(const QQmlRefPointer &a, const QQmlRefPointer &b) { return a.o == b.o; }
|
||||
friend bool operator!=(const QQmlRefPointer &a, const QQmlRefPointer &b) { return !(a == b); }
|
||||
friend bool operator==(const QQmlRefPointer &a, const QQmlRefPointer &b) noexcept
|
||||
{
|
||||
return a.o == b.o;
|
||||
}
|
||||
|
||||
friend bool operator!=(const QQmlRefPointer &a, const QQmlRefPointer &b) noexcept
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
friend size_t qHash(const QQmlRefPointer &v, size_t seed = 0) noexcept
|
||||
{
|
||||
return qHash(v.o, seed);
|
||||
}
|
||||
|
||||
void reset(T *t = nullptr)
|
||||
{
|
||||
|
|
|
@ -477,13 +477,43 @@ static void uniqueRevisions(QVector<QTypeRevision> *revisions, QTypeRevision def
|
|||
revisions->erase(it, revisions->end());
|
||||
}
|
||||
|
||||
static QQmlType::SingletonInstanceInfo::ConstPtr singletonInstanceInfo(
|
||||
const QQmlPrivate::RegisterSingletonType &type)
|
||||
{
|
||||
QQmlType::SingletonInstanceInfo::Ptr siinfo = QQmlType::SingletonInstanceInfo::create();
|
||||
siinfo->scriptCallback = type.scriptApi;
|
||||
siinfo->qobjectCallback = type.qObjectApi;
|
||||
siinfo->typeName = QString::fromUtf8(type.typeName);
|
||||
return QQmlType::SingletonInstanceInfo::ConstPtr(
|
||||
siinfo.take(), QQmlType::SingletonInstanceInfo::ConstPtr::Adopt);
|
||||
}
|
||||
|
||||
static QQmlType::SingletonInstanceInfo::ConstPtr singletonInstanceInfo(
|
||||
const QQmlPrivate::RegisterCompositeSingletonType &type)
|
||||
{
|
||||
QQmlType::SingletonInstanceInfo::Ptr siinfo = QQmlType::SingletonInstanceInfo::create();
|
||||
siinfo->url = QQmlTypeLoader::normalize(type.url);
|
||||
siinfo->typeName = QString::fromUtf8(type.typeName);
|
||||
return QQmlType::SingletonInstanceInfo::ConstPtr(
|
||||
siinfo.take(), QQmlType::SingletonInstanceInfo::ConstPtr::Adopt);
|
||||
}
|
||||
|
||||
static int finalizeType(const QQmlType &dtype)
|
||||
{
|
||||
if (!dtype.isValid())
|
||||
return -1;
|
||||
|
||||
QQmlMetaType::registerUndeletableType(dtype);
|
||||
return dtype.index();
|
||||
}
|
||||
|
||||
/*
|
||||
This method is "over generalized" to allow us to (potentially) register more types of things in
|
||||
the future without adding exported symbols.
|
||||
*/
|
||||
int QQmlPrivate::qmlregister(RegistrationType type, void *data)
|
||||
{
|
||||
QQmlType dtype;
|
||||
|
||||
switch (type) {
|
||||
case AutoParentRegistration:
|
||||
return QQmlMetaType::registerAutoParentFunction(
|
||||
|
@ -616,6 +646,8 @@ int QQmlPrivate::qmlregister(RegistrationType type, void *data)
|
|||
type.extensionMetaObject,
|
||||
QTypeRevision()
|
||||
};
|
||||
const QQmlType::SingletonInstanceInfo::ConstPtr siinfo
|
||||
= singletonInstanceInfo(revisionRegistration);
|
||||
|
||||
const QTypeRevision added = revisionClassInfo(
|
||||
type.classInfoMetaObject, "QML.AddedInVersion",
|
||||
|
@ -644,7 +676,8 @@ int QQmlPrivate::qmlregister(RegistrationType type, void *data)
|
|||
revisionRegistration.qObjectApi = type.qObjectApi;
|
||||
}
|
||||
|
||||
const int id = qmlregister(SingletonRegistration, &revisionRegistration);
|
||||
const int id = finalizeType(
|
||||
QQmlMetaType::registerSingletonType(revisionRegistration, siinfo));
|
||||
if (type.qmlTypeIds)
|
||||
type.qmlTypeIds->append(id);
|
||||
}
|
||||
|
@ -685,32 +718,30 @@ int QQmlPrivate::qmlregister(RegistrationType type, void *data)
|
|||
break;
|
||||
}
|
||||
case TypeRegistration:
|
||||
dtype = QQmlMetaType::registerType(*reinterpret_cast<RegisterType *>(data));
|
||||
break;
|
||||
return finalizeType(
|
||||
QQmlMetaType::registerType(*reinterpret_cast<RegisterType *>(data)));
|
||||
case InterfaceRegistration:
|
||||
dtype = QQmlMetaType::registerInterface(*reinterpret_cast<RegisterInterface *>(data));
|
||||
break;
|
||||
return finalizeType(
|
||||
QQmlMetaType::registerInterface(*reinterpret_cast<RegisterInterface *>(data)));
|
||||
case SingletonRegistration:
|
||||
dtype = QQmlMetaType::registerSingletonType(*reinterpret_cast<RegisterSingletonType *>(data));
|
||||
break;
|
||||
return finalizeType(QQmlMetaType::registerSingletonType(
|
||||
*reinterpret_cast<RegisterSingletonType *>(data),
|
||||
singletonInstanceInfo(*reinterpret_cast<RegisterSingletonType *>(data))));
|
||||
case CompositeRegistration:
|
||||
dtype = QQmlMetaType::registerCompositeType(*reinterpret_cast<RegisterCompositeType *>(data));
|
||||
break;
|
||||
return finalizeType(QQmlMetaType::registerCompositeType(
|
||||
*reinterpret_cast<RegisterCompositeType *>(data)));
|
||||
case CompositeSingletonRegistration:
|
||||
dtype = QQmlMetaType::registerCompositeSingletonType(*reinterpret_cast<RegisterCompositeSingletonType *>(data));
|
||||
break;
|
||||
return finalizeType(QQmlMetaType::registerCompositeSingletonType(
|
||||
*reinterpret_cast<RegisterCompositeSingletonType *>(data),
|
||||
singletonInstanceInfo(*reinterpret_cast<RegisterCompositeSingletonType *>(data))));
|
||||
case SequentialContainerRegistration:
|
||||
dtype = QQmlMetaType::registerSequentialContainer(*reinterpret_cast<RegisterSequentialContainer *>(data));
|
||||
break;
|
||||
return finalizeType(QQmlMetaType::registerSequentialContainer(
|
||||
*reinterpret_cast<RegisterSequentialContainer *>(data)));
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!dtype.isValid())
|
||||
return -1;
|
||||
|
||||
QQmlMetaType::registerUndeletableType(dtype);
|
||||
return dtype.index();
|
||||
return -1;
|
||||
}
|
||||
|
||||
void QQmlPrivate::qmlunregister(RegistrationType type, quintptr data)
|
||||
|
|
|
@ -1906,14 +1906,13 @@ QJSValue QQmlEnginePrivate::singletonInstance<QJSValue>(const QQmlType &type)
|
|||
{
|
||||
Q_Q(QQmlEngine);
|
||||
|
||||
QJSValue value = singletonInstances.value(type);
|
||||
if (!value.isUndefined()) {
|
||||
return value;
|
||||
}
|
||||
|
||||
QQmlType::SingletonInstanceInfo *siinfo = type.singletonInstanceInfo();
|
||||
QQmlType::SingletonInstanceInfo::ConstPtr siinfo = type.singletonInstanceInfo();
|
||||
Q_ASSERT(siinfo != nullptr);
|
||||
|
||||
QJSValue value = singletonInstances.value(siinfo);
|
||||
if (!value.isUndefined())
|
||||
return value;
|
||||
|
||||
if (siinfo->scriptCallback) {
|
||||
value = siinfo->scriptCallback(q, q);
|
||||
if (value.isQObject()) {
|
||||
|
@ -1922,7 +1921,7 @@ QJSValue QQmlEnginePrivate::singletonInstance<QJSValue>(const QQmlType &type)
|
|||
// should behave identically to QML singleton types.
|
||||
q->setContextForObject(o, new QQmlContext(q->rootContext(), q));
|
||||
}
|
||||
singletonInstances.convertAndInsert(v4engine(), type, &value);
|
||||
singletonInstances.convertAndInsert(v4engine(), siinfo, &value);
|
||||
|
||||
} else if (siinfo->qobjectCallback) {
|
||||
QObject *o = siinfo->qobjectCallback(q, q);
|
||||
|
@ -1951,7 +1950,7 @@ QJSValue QQmlEnginePrivate::singletonInstance<QJSValue>(const QQmlType &type)
|
|||
}
|
||||
|
||||
value = q->newQObject(o);
|
||||
singletonInstances.convertAndInsert(v4engine(), type, &value);
|
||||
singletonInstances.convertAndInsert(v4engine(), siinfo, &value);
|
||||
} else if (!siinfo->url.isEmpty()) {
|
||||
QQmlComponent component(q, siinfo->url, QQmlComponent::PreferSynchronous);
|
||||
if (component.isError()) {
|
||||
|
@ -1962,7 +1961,7 @@ QJSValue QQmlEnginePrivate::singletonInstance<QJSValue>(const QQmlType &type)
|
|||
}
|
||||
QObject *o = component.beginCreate(q->rootContext());
|
||||
value = q->newQObject(o);
|
||||
singletonInstances.convertAndInsert(v4engine(), type, &value);
|
||||
singletonInstances.convertAndInsert(v4engine(), siinfo, &value);
|
||||
component.completeCreate();
|
||||
}
|
||||
|
||||
|
|
|
@ -252,10 +252,12 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
class SingletonInstances : private QHash<QQmlType, QJSValue>
|
||||
class SingletonInstances : private QHash<QQmlType::SingletonInstanceInfo::ConstPtr, QJSValue>
|
||||
{
|
||||
public:
|
||||
void convertAndInsert(QV4::ExecutionEngine *engine, const QQmlType &type, QJSValue *value)
|
||||
void convertAndInsert(
|
||||
QV4::ExecutionEngine *engine, const QQmlType::SingletonInstanceInfo::ConstPtr &type,
|
||||
QJSValue *value)
|
||||
{
|
||||
QJSValuePrivate::manageStringOnV4Heap(engine, value);
|
||||
insert(type, *value);
|
||||
|
@ -263,11 +265,11 @@ private:
|
|||
|
||||
void clear()
|
||||
{
|
||||
const auto canDelete = [](QObject *instance, const auto &type) -> bool {
|
||||
const auto canDelete = [](QObject *instance, const auto &siinfo) -> bool {
|
||||
if (!instance)
|
||||
return false;
|
||||
|
||||
if (!type.singletonInstanceInfo()->url.isEmpty())
|
||||
if (!siinfo->url.isEmpty())
|
||||
return true;
|
||||
|
||||
const auto *ddata = QQmlData::get(instance, false);
|
||||
|
@ -287,11 +289,11 @@ private:
|
|||
delete instance;
|
||||
}
|
||||
|
||||
QHash<QQmlType, QJSValue>::clear();
|
||||
QHash<QQmlType::SingletonInstanceInfo::ConstPtr, QJSValue>::clear();
|
||||
}
|
||||
|
||||
using QHash<QQmlType, QJSValue>::value;
|
||||
using QHash<QQmlType, QJSValue>::take;
|
||||
using QHash<QQmlType::SingletonInstanceInfo::ConstPtr, QJSValue>::value;
|
||||
using QHash<QQmlType::SingletonInstanceInfo::ConstPtr, QJSValue>::take;
|
||||
};
|
||||
|
||||
SingletonInstances singletonInstances;
|
||||
|
|
|
@ -70,8 +70,10 @@ static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data,
|
|||
return d;
|
||||
}
|
||||
|
||||
static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, const QString &elementName,
|
||||
const QQmlPrivate::RegisterSingletonType &type)
|
||||
static QQmlTypePrivate *createQQmlType(
|
||||
QQmlMetaTypeData *data, const QString &elementName,
|
||||
const QQmlPrivate::RegisterSingletonType &type,
|
||||
const QQmlType::SingletonInstanceInfo::ConstPtr &siinfo)
|
||||
{
|
||||
auto *d = new QQmlTypePrivate(QQmlType::SingletonType);
|
||||
data->registerType(d);
|
||||
|
@ -85,10 +87,7 @@ static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, const QString &el
|
|||
d->revision = type.revision;
|
||||
}
|
||||
|
||||
d->extraData.singletonTypeData->singletonInstanceInfo = new QQmlType::SingletonInstanceInfo;
|
||||
d->extraData.singletonTypeData->singletonInstanceInfo->scriptCallback = type.scriptApi;
|
||||
d->extraData.singletonTypeData->singletonInstanceInfo->qobjectCallback = type.qObjectApi;
|
||||
d->extraData.singletonTypeData->singletonInstanceInfo->typeName = QString::fromUtf8(type.typeName);
|
||||
d->extraData.singletonTypeData->singletonInstanceInfo = siinfo;
|
||||
d->extraData.singletonTypeData->extFunc = type.extensionObjectCreate;
|
||||
d->extraData.singletonTypeData->extMetaObject = type.extensionMetaObject;
|
||||
|
||||
|
@ -181,8 +180,10 @@ static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, const QString &el
|
|||
return d;
|
||||
}
|
||||
|
||||
static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, const QString &elementName,
|
||||
const QQmlPrivate::RegisterCompositeSingletonType &type)
|
||||
static QQmlTypePrivate *createQQmlType(
|
||||
QQmlMetaTypeData *data, const QString &elementName,
|
||||
const QQmlPrivate::RegisterCompositeSingletonType &type,
|
||||
const QQmlType::SingletonInstanceInfo::ConstPtr &siinfo)
|
||||
{
|
||||
auto *d = new QQmlTypePrivate(QQmlType::CompositeSingletonType);
|
||||
data->registerType(d);
|
||||
|
@ -190,12 +191,9 @@ static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, const QString &el
|
|||
|
||||
d->version = type.version;
|
||||
|
||||
const QUrl normalized = QQmlTypeLoader::normalize(type.url);
|
||||
d->extraData.singletonTypeData->singletonInstanceInfo = new QQmlType::SingletonInstanceInfo;
|
||||
d->extraData.singletonTypeData->singletonInstanceInfo->url = normalized;
|
||||
d->extraData.singletonTypeData->singletonInstanceInfo->typeName = QString::fromUtf8(type.typeName);
|
||||
d->extraData.singletonTypeData->singletonInstanceInfo = siinfo;
|
||||
addQQmlMetaTypeInterfaces(
|
||||
d, QQmlPropertyCacheCreatorBase::createClassNameTypeByUrl(normalized));
|
||||
d, QQmlPropertyCacheCreatorBase::createClassNameTypeByUrl(siinfo->url));
|
||||
return d;
|
||||
}
|
||||
|
||||
|
@ -490,7 +488,9 @@ QQmlType QQmlMetaType::registerType(const QQmlPrivate::RegisterType &type)
|
|||
return QQmlType(priv);
|
||||
}
|
||||
|
||||
QQmlType QQmlMetaType::registerSingletonType(const QQmlPrivate::RegisterSingletonType &type)
|
||||
QQmlType QQmlMetaType::registerSingletonType(
|
||||
const QQmlPrivate::RegisterSingletonType &type,
|
||||
const QQmlType::SingletonInstanceInfo::ConstPtr &siinfo)
|
||||
{
|
||||
if (type.structVersion > 1)
|
||||
qFatal("qmlRegisterType(): Cannot mix incompatible QML versions.");
|
||||
|
@ -503,14 +503,16 @@ QQmlType QQmlMetaType::registerSingletonType(const QQmlPrivate::RegisterSingleto
|
|||
return QQmlType();
|
||||
}
|
||||
|
||||
QQmlTypePrivate *priv = createQQmlType(data, typeName, type);
|
||||
QQmlTypePrivate *priv = createQQmlType(data, typeName, type, siinfo);
|
||||
|
||||
addTypeToData(priv, data);
|
||||
|
||||
return QQmlType(priv);
|
||||
}
|
||||
|
||||
QQmlType QQmlMetaType::registerCompositeSingletonType(const QQmlPrivate::RegisterCompositeSingletonType &type)
|
||||
QQmlType QQmlMetaType::registerCompositeSingletonType(
|
||||
const QQmlPrivate::RegisterCompositeSingletonType &type,
|
||||
const QQmlType::SingletonInstanceInfo::ConstPtr &siinfo)
|
||||
{
|
||||
if (type.structVersion > 1)
|
||||
qFatal("qmlRegisterType(): Cannot mix incompatible QML versions.");
|
||||
|
@ -527,11 +529,11 @@ QQmlType QQmlMetaType::registerCompositeSingletonType(const QQmlPrivate::Registe
|
|||
return QQmlType();
|
||||
}
|
||||
|
||||
QQmlTypePrivate *priv = createQQmlType(data, typeName, type);
|
||||
QQmlTypePrivate *priv = createQQmlType(data, typeName, type, siinfo);
|
||||
addTypeToData(priv, data);
|
||||
|
||||
QQmlMetaTypeData::Files *files = fileImport ? &(data->urlToType) : &(data->urlToNonFileImportType);
|
||||
files->insert(QQmlTypeLoader::normalize(type.url), priv);
|
||||
files->insert(siinfo->url, priv);
|
||||
|
||||
return QQmlType(priv);
|
||||
}
|
||||
|
@ -627,9 +629,12 @@ static QQmlType createTypeForUrl(
|
|||
priv->version = version;
|
||||
|
||||
if (mode == QQmlMetaType::Singleton) {
|
||||
priv->extraData.singletonTypeData->singletonInstanceInfo = new QQmlType::SingletonInstanceInfo;
|
||||
priv->extraData.singletonTypeData->singletonInstanceInfo->url = url;
|
||||
priv->extraData.singletonTypeData->singletonInstanceInfo->typeName = typeName;
|
||||
QQmlType::SingletonInstanceInfo::Ptr siinfo = QQmlType::SingletonInstanceInfo::create();
|
||||
siinfo->url = url;
|
||||
siinfo->typeName = typeName;
|
||||
priv->extraData.singletonTypeData->singletonInstanceInfo =
|
||||
QQmlType::SingletonInstanceInfo::ConstPtr(
|
||||
siinfo.take(), QQmlType::SingletonInstanceInfo::ConstPtr::Adopt);
|
||||
} else {
|
||||
priv->extraData.compositeTypeData = url;
|
||||
}
|
||||
|
|
|
@ -81,8 +81,12 @@ public:
|
|||
static void unregisterInternalCompositeType(QMetaType metaType, QMetaType listMetaType);
|
||||
static QQmlType registerType(const QQmlPrivate::RegisterType &type);
|
||||
static QQmlType registerInterface(const QQmlPrivate::RegisterInterface &type);
|
||||
static QQmlType registerSingletonType(const QQmlPrivate::RegisterSingletonType &type);
|
||||
static QQmlType registerCompositeSingletonType(const QQmlPrivate::RegisterCompositeSingletonType &type);
|
||||
static QQmlType registerSingletonType(
|
||||
const QQmlPrivate::RegisterSingletonType &type,
|
||||
const QQmlType::SingletonInstanceInfo::ConstPtr &siinfo);
|
||||
static QQmlType registerCompositeSingletonType(
|
||||
const QQmlPrivate::RegisterCompositeSingletonType &type,
|
||||
const QQmlType::SingletonInstanceInfo::ConstPtr &siinfo);
|
||||
static QQmlType registerCompositeType(const QQmlPrivate::RegisterCompositeType &type);
|
||||
static RegistrationResult registerPluginTypes(QObject *instance, const QString &basePath,
|
||||
const QString &uri, const QString &typeNamespace,
|
||||
|
|
|
@ -77,7 +77,7 @@ QQmlTypePrivate::~QQmlTypePrivate()
|
|||
break;
|
||||
case QQmlType::SingletonType:
|
||||
case QQmlType::CompositeSingletonType:
|
||||
delete extraData.singletonTypeData->singletonInstanceInfo;
|
||||
extraData.singletonTypeData->singletonInstanceInfo.reset();
|
||||
delete extraData.singletonTypeData;
|
||||
break;
|
||||
case QQmlType::CompositeType:
|
||||
|
@ -508,12 +508,12 @@ QObject *QQmlType::createWithQQmlData() const
|
|||
return instance;
|
||||
}
|
||||
|
||||
QQmlType::SingletonInstanceInfo *QQmlType::singletonInstanceInfo() const
|
||||
QQmlType::SingletonInstanceInfo::ConstPtr QQmlType::singletonInstanceInfo() const
|
||||
{
|
||||
if (!d)
|
||||
return nullptr;
|
||||
return {};
|
||||
if (d->regType != SingletonType && d->regType != CompositeSingletonType)
|
||||
return nullptr;
|
||||
return {};
|
||||
return d->extraData.singletonTypeData->singletonInstanceInfo;
|
||||
}
|
||||
|
||||
|
|
|
@ -119,14 +119,24 @@ public:
|
|||
|
||||
bool isInlineComponentType() const;
|
||||
|
||||
struct Q_QML_PRIVATE_EXPORT SingletonInstanceInfo
|
||||
struct Q_QML_PRIVATE_EXPORT SingletonInstanceInfo final
|
||||
: public QQmlRefCounted<SingletonInstanceInfo>
|
||||
{
|
||||
using Ptr = QQmlRefPointer<SingletonInstanceInfo>;
|
||||
using ConstPtr = QQmlRefPointer<const SingletonInstanceInfo>;
|
||||
|
||||
static Ptr create() { return Ptr(new SingletonInstanceInfo, Ptr::Adopt); }
|
||||
|
||||
std::function<QJSValue(QQmlEngine *, QJSEngine *)> scriptCallback = {};
|
||||
std::function<QObject *(QQmlEngine *, QJSEngine *)> qobjectCallback = {};
|
||||
QString typeName;
|
||||
QUrl url; // used by composite singletons
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY_MOVE(SingletonInstanceInfo)
|
||||
SingletonInstanceInfo() = default;
|
||||
};
|
||||
SingletonInstanceInfo *singletonInstanceInfo() const;
|
||||
SingletonInstanceInfo::ConstPtr singletonInstanceInfo() const;
|
||||
|
||||
QUrl sourceUrl() const;
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@ public:
|
|||
|
||||
struct QQmlSingletonTypeData
|
||||
{
|
||||
QQmlType::SingletonInstanceInfo *singletonInstanceInfo;
|
||||
QQmlType::SingletonInstanceInfo::ConstPtr singletonInstanceInfo;
|
||||
QObject *(*extFunc)(QObject *);
|
||||
const QMetaObject *extMetaObject;
|
||||
};
|
||||
|
|
|
@ -98,8 +98,8 @@ void registerTypes()
|
|||
qmlRegisterType<ImmediateProperties>("Test", 1, 0, "ImmediateProperties");
|
||||
|
||||
qmlRegisterTypesAndRevisions<Extended, Foreign, ForeignExtended>("Test", 1);
|
||||
qmlRegisterTypesAndRevisions<BareSingleton>("Test", 1);
|
||||
qmlRegisterTypesAndRevisions<UncreatableSingleton>("Test", 1);
|
||||
qmlRegisterTypesAndRevisions<BareSingleton>("Test", 11);
|
||||
qmlRegisterTypesAndRevisions<UncreatableSingleton>("Test", 11);
|
||||
|
||||
// Metatype/namespace variation one: Register namespace first
|
||||
|
||||
|
|
|
@ -1549,6 +1549,7 @@ class BareSingleton : public QObject
|
|||
Q_OBJECT
|
||||
QML_SINGLETON
|
||||
QML_ELEMENT
|
||||
QML_ADDED_IN_VERSION(1, 0)
|
||||
|
||||
public:
|
||||
BareSingleton(QObject *parent = nullptr) : QObject(parent)
|
||||
|
@ -1562,6 +1563,7 @@ class UncreatableSingleton : public QObject
|
|||
Q_OBJECT
|
||||
QML_SINGLETON
|
||||
QML_ELEMENT
|
||||
QML_ADDED_IN_VERSION(1, 0)
|
||||
|
||||
public:
|
||||
static UncreatableSingleton *instance();
|
||||
|
|
|
@ -431,6 +431,8 @@ private slots:
|
|||
|
||||
void callMethodOfAttachedDerived();
|
||||
|
||||
void multiVersionSingletons();
|
||||
|
||||
private:
|
||||
QQmlEngine engine;
|
||||
QStringList defaultImportPathList;
|
||||
|
@ -8267,6 +8269,20 @@ void tst_qqmllanguage::callMethodOfAttachedDerived()
|
|||
QCOMPARE(o->property("v").toInt(), 99);
|
||||
}
|
||||
|
||||
void tst_qqmllanguage::multiVersionSingletons()
|
||||
{
|
||||
QQmlEngine engine;
|
||||
|
||||
for (const char *name : { "BareSingleton", "UncreatableSingleton"}) {
|
||||
const int id1 = qmlTypeId("Test", 1, 0, name);
|
||||
const int id2 = qmlTypeId("Test", 11, 0, name);
|
||||
QVERIFY(id1 != id2);
|
||||
const QJSValue value1 = engine.singletonInstance<QJSValue>(id1);
|
||||
const QJSValue value2 = engine.singletonInstance<QJSValue>(id2);
|
||||
QVERIFY(value1.strictlyEquals(value2));
|
||||
}
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_qqmllanguage)
|
||||
|
||||
#include "tst_qqmllanguage.moc"
|
||||
|
|
|
@ -262,7 +262,7 @@ QSet<const QMetaObject *> collectReachableMetaObjects(QQmlEngine *engine,
|
|||
QObject *object = nullptr;
|
||||
|
||||
if (ty.isSingleton()) {
|
||||
QQmlType::SingletonInstanceInfo *siinfo = ty.singletonInstanceInfo();
|
||||
QQmlType::SingletonInstanceInfo::ConstPtr siinfo = ty.singletonInstanceInfo();
|
||||
if (!siinfo) {
|
||||
std::cerr << "Internal error, " << qPrintable(tyName)
|
||||
<< "(" << qPrintable( QString::fromUtf8(ty.typeName()) ) << ")"
|
||||
|
|
Loading…
Reference in New Issue