From 6ebf215fdaf2d757ab90ae4d46c4b938e978e2dc Mon Sep 17 00:00:00 2001 From: Glenn Watson Date: Tue, 24 Jul 2012 11:41:50 +1000 Subject: Add type name to singleton (module api) implementations. This change renames the previous module api implementation to singleton types. When a singleton type is registered, a type name must be provided that is used when accessing the API from QML. This makes the implementation more consistent with the rest of QML. Task-number: QTBUG-26549 Change-Id: Iab0bb1ccf516bd3ae20aee562a64d22976e0aecd Reviewed-by: Chris Adams --- src/qml/qml/qqml.h | 16 ++--- src/qml/qml/qqmlengine.cpp | 26 ++++---- src/qml/qml/qqmlengine_p.h | 4 +- src/qml/qml/qqmlimport.cpp | 19 ++++-- src/qml/qml/qqmlmetatype.cpp | 124 ++++++++++++++++++++++++++------------ src/qml/qml/qqmlmetatype_p.h | 25 +++++--- src/qml/qml/qqmlprivate.h | 5 +- src/qml/qml/qqmltypenamecache.cpp | 26 ++++++-- src/qml/qml/qqmltypenamecache_p.h | 7 ++- src/qml/qml/v4/qv4bindings.cpp | 16 ++--- src/qml/qml/v4/qv4compiler.cpp | 2 +- src/qml/qml/v4/qv4irbuilder.cpp | 14 ++--- src/qml/qml/v8/qv8typewrapper.cpp | 84 +++++++++++++------------- 13 files changed, 228 insertions(+), 140 deletions(-) (limited to 'src/qml/qml') diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h index 528f8e6416..a10ed0c5e8 100644 --- a/src/qml/qml/qqml.h +++ b/src/qml/qml/qqml.h @@ -433,33 +433,33 @@ QObject *qmlAttachedPropertiesObject(const QObject *obj, bool create = true) Q_QML_EXPORT void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor); -inline int qmlRegisterModuleApi(const char *uri, int versionMajor, int versionMinor, +inline int qmlRegisterSingletonType(const char *uri, int versionMajor, int versionMinor, const char *typeName, QJSValue (*callback)(QQmlEngine *, QJSEngine *)) { - QQmlPrivate::RegisterModuleApi api = { + QQmlPrivate::RegisterSingletonType api = { 0, - uri, versionMajor, versionMinor, + uri, versionMajor, versionMinor, typeName, callback, 0, 0 }; - return QQmlPrivate::qmlregister(QQmlPrivate::ModuleApiRegistration, &api); + return QQmlPrivate::qmlregister(QQmlPrivate::SingletonRegistration, &api); } template -inline int qmlRegisterModuleApi(const char *uri, int versionMajor, int versionMinor, +inline int qmlRegisterSingletonType(const char *uri, int versionMajor, int versionMinor, const char *typeName, QObject *(*callback)(QQmlEngine *, QJSEngine *)) { - QQmlPrivate::RegisterModuleApi api = { + QQmlPrivate::RegisterSingletonType api = { 1, - uri, versionMajor, versionMinor, + uri, versionMajor, versionMinor, typeName, 0, callback, &T::staticMetaObject }; - return QQmlPrivate::qmlregister(QQmlPrivate::ModuleApiRegistration, &api); + return QQmlPrivate::qmlregister(QQmlPrivate::SingletonRegistration, &api); } QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 589d7b7c8a..bce5579f31 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -463,7 +463,7 @@ QQmlEnginePrivate::~QQmlEnginePrivate() (*iter)->release(); for(QHash, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter) (*iter)->release(); - for(QHash::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) { + for (QHash::Iterator iter = singletonTypeInstances.begin(); iter != singletonTypeInstances.end(); ++iter) { delete (*iter)->qobjectApi; delete *iter; } @@ -735,23 +735,23 @@ QQmlEngine::~QQmlEngine() } // Emit onDestruction signals for the root context before - // we destroy the contexts, engine, Module APIs etc. that + // we destroy the contexts, engine, Singleton Types etc. that // may be required to handle the destruction signal. QQmlContextData::get(rootContext())->emitDestruction(); - // if we are the parent of any of the qobject module api instances, + // if we are the parent of any of the qobject singleton type instances, // we need to remove them from our internal list, in order to prevent // a segfault in engine private dtor. - QList keys = d->moduleApiInstances.keys(); + QList keys = d->singletonTypeInstances.keys(); QObject *currQObjectApi = 0; - QQmlMetaType::ModuleApiInstance *currInstance = 0; - foreach (const QQmlMetaType::ModuleApi &key, keys) { - currInstance = d->moduleApiInstances.value(key); + QQmlMetaType::SingletonInstance *currInstance = 0; + foreach (const QQmlMetaType::SingletonType &key, keys) { + currInstance = d->singletonTypeInstances.value(key); currQObjectApi = currInstance->qobjectApi; if (this->children().contains(currQObjectApi)) { delete currQObjectApi; delete currInstance; - d->moduleApiInstances.remove(key); + d->singletonTypeInstances.remove(key); } } @@ -1881,18 +1881,18 @@ QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersi return raw; } -QQmlMetaType::ModuleApiInstance * -QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module) +QQmlMetaType::SingletonInstance * +QQmlEnginePrivate::singletonTypeInstance(const QQmlMetaType::SingletonType &module) { Locker locker(this); - QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module); + QQmlMetaType::SingletonInstance *a = singletonTypeInstances.value(module); if (!a) { - a = new QQmlMetaType::ModuleApiInstance; + a = new QQmlMetaType::SingletonInstance; a->scriptCallback = module.script; a->qobjectCallback = module.qobject; a->instanceMetaObject = module.instanceMetaObject; - moduleApiInstances.insert(module, a); + singletonTypeInstances.insert(module, a); } return a; diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h index b90d597be6..f62e99b3ce 100644 --- a/src/qml/qml/qqmlengine_p.h +++ b/src/qml/qml/qqmlengine_p.h @@ -223,7 +223,7 @@ public: inline static void deleteInEngineThread(QQmlEngine *, T *); // These methods may be called from the loader thread - QQmlMetaType::ModuleApiInstance *moduleApiInstance(const QQmlMetaType::ModuleApi &module); + QQmlMetaType::SingletonInstance *singletonTypeInstance(const QQmlMetaType::SingletonType &module); // These methods may be called from the loader thread inline QQmlPropertyCache *cache(QObject *obj); @@ -305,7 +305,7 @@ private: // These members must be protected by a QQmlEnginePrivate::Locker as they are required by // the threaded loader. Only access them through their respective accessor methods. - QHash moduleApiInstances; + QHash singletonTypeInstances; QHash propertyCache; QHash, QQmlPropertyCache *> typePropertyCache; QHash m_qmlLists; diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index e7133992d9..6475621bee 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -299,6 +299,15 @@ void QQmlImports::populateCache(QQmlTypeNameCache *cache, QQmlEngine *engine) co QQmlTypeModule *module = QQmlMetaType::typeModule(import->uri, import->majversion); if (module) cache->m_anonymousImports.append(QQmlTypeModuleVersion(module, import->minversion)); + + QQmlMetaType::SingletonType singletonType = QQmlMetaType::singletonType(import->uri, import->majversion, + import->minversion); + if (singletonType.script || singletonType.qobject) { + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine); + QQmlMetaType::SingletonInstance *apiInstance = ep->singletonTypeInstance(singletonType); + + cache->addSingletonType(singletonType.typeName, apiInstance); + } } for (QQmlImportNamespace *ns = d->qualifiedSets.first(); ns; ns = d->qualifiedSets.next(ns)) { @@ -313,12 +322,14 @@ void QQmlImports::populateCache(QQmlTypeNameCache *cache, QQmlEngine *engine) co typeimport.modules.append(QQmlTypeModuleVersion(module, import->minversion)); } - QQmlMetaType::ModuleApi moduleApi = QQmlMetaType::moduleApi(import->uri, import->majversion, + QQmlMetaType::SingletonType singletonType = QQmlMetaType::singletonType(import->uri, import->majversion, import->minversion); - if (moduleApi.script || moduleApi.qobject) { - QQmlTypeNameCache::Import &import = cache->m_namedImports[set.prefix]; + if (singletonType.script || singletonType.qobject) { QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine); - import.moduleApi = ep->moduleApiInstance(moduleApi); + QQmlMetaType::SingletonInstance *apiInstance = ep->singletonTypeInstance(singletonType); + + cache->add(set.prefix); + cache->addSingletonType(singletonType.typeName, apiInstance, set.prefix); } } } diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index b3a16b034c..35ff9fd5d1 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -94,14 +94,35 @@ struct QQmlMetaTypeData typedef QHash TypeModules; TypeModules uriToModule; - struct ModuleApiList { - ModuleApiList() : sorted(true) {} - QList moduleApis; + struct SingletonTypeList { + SingletonTypeList() : sorted(true) {} + QList singletonTypes; bool sorted; }; - typedef QStringHash ModuleApis; - ModuleApis moduleApis; - int moduleApiCount; + typedef QStringHash SingletonTypes; + SingletonTypes singletonTypes; + int singletonTypeCount; + + bool singletonTypeExists(const QString &uri, const QString &typeName, int major, int minor) + { + QQmlMetaTypeData::SingletonTypeList *apiList = singletonTypes.value(uri); + if (apiList) { + for (int i=0 ; i < apiList->singletonTypes.size() ; ++i) { + const QQmlMetaType::SingletonType &import = apiList->singletonTypes.at(i); + if (import.major == major && import.minor == minor && typeName == import.typeName) + return true; + } + } + + return false; + } + + bool typeExists(const QString &uri, const QString &typeName, int major, int minor) + { + QQmlMetaTypeData::VersionedUri versionedUri(uri, major); + QQmlTypeModule *module = uriToModule.value(versionedUri); + return module && module->typeNoLock(typeName, minor) != 0; + } QBitArray objects; QBitArray interfaces; @@ -141,7 +162,7 @@ static uint qHash(const QQmlMetaTypeData::VersionedUri &v) } QQmlMetaTypeData::QQmlMetaTypeData() -: moduleApiCount(0) +: singletonTypeCount(0) { } @@ -779,6 +800,20 @@ void QQmlTypeModulePrivate::add(QQmlType *type) list.append(type); } +QQmlType *QQmlTypeModule::typeNoLock(const QString &name, int minor) +{ + // Expected that the caller has already handled locking metaTypeDataLock + + QList *types = d->typeHash.value(name); + if (!types) return 0; + + for (int ii = 0; ii < types->count(); ++ii) + if (types->at(ii)->minorVersion() <= minor) + return types->at(ii); + + return 0; +} + QQmlType *QQmlTypeModule::type(const QHashedStringRef &name, int minor) { QReadLocker lock(metaTypeDataLock()); @@ -911,6 +946,11 @@ int registerType(const QQmlPrivate::RegisterType &type) if (type.uri && type.elementName) { QString nameSpace = moduleFromUtf8(type.uri); + if (data->singletonTypeExists(nameSpace, type.elementName, type.versionMajor, type.versionMinor)) { + qWarning("Cannot register type %s in uri %s %d.%d (a conflicting singleton type already exists)", qPrintable(type.elementName), qPrintable(nameSpace), type.versionMajor, type.versionMinor); + return -1; + } + if (!data->typeRegistrationNamespace.isEmpty()) { // We can only install types into the registered namespace if (nameSpace != data->typeRegistrationNamespace) { @@ -966,28 +1006,38 @@ int registerType(const QQmlPrivate::RegisterType &type) return index; } -int registerModuleApi(const QQmlPrivate::RegisterModuleApi &api) +int registerSingletonType(const QQmlPrivate::RegisterSingletonType &api) { QWriteLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); QString uri = QString::fromUtf8(api.uri); - QQmlMetaType::ModuleApi import; + QQmlMetaType::SingletonType import; import.major = api.versionMajor; import.minor = api.versionMinor; import.script = api.scriptApi; import.qobject = api.qobjectApi; + Q_ASSERT(api.typeName); + import.typeName = QString::fromUtf8(api.typeName); import.instanceMetaObject = (api.qobjectApi && api.version >= 1) ? api.instanceMetaObject : 0; // BC with version 0. - int index = data->moduleApiCount++; + if (data->singletonTypeExists(uri, import.typeName, import.major, import.minor)) { + qWarning("Cannot register singleton type %s in uri %s %d.%d (a conflicting singleton type already exists)", qPrintable(import.typeName), qPrintable(uri), import.major, import.minor); + return -1; + } else if (data->typeExists(uri, import.typeName, import.major, import.minor)) { + qWarning("Cannot register singleton type %s in uri %s %d.%d (a conflicting type already exists)", qPrintable(import.typeName), qPrintable(uri), import.major, import.minor); + return -1; + } + + int index = data->singletonTypeCount++; - QQmlMetaTypeData::ModuleApiList *apiList = data->moduleApis.value(uri); + QQmlMetaTypeData::SingletonTypeList *apiList = data->singletonTypes.value(uri); if (!apiList) { - QQmlMetaTypeData::ModuleApiList apis; - apis.moduleApis << import; - data->moduleApis.insert(uri, apis); + QQmlMetaTypeData::SingletonTypeList apis; + apis.singletonTypes << import; + data->singletonTypes.insert(uri, apis); } else { - apiList->moduleApis << import; + apiList->singletonTypes << import; apiList->sorted = false; } @@ -1007,8 +1057,8 @@ int QQmlPrivate::qmlregister(RegistrationType type, void *data) return registerInterface(*reinterpret_cast(data)); } else if (type == AutoParentRegistration) { return registerAutoParentFunction(*reinterpret_cast(data)); - } else if (type == ModuleApiRegistration) { - return registerModuleApi(*reinterpret_cast(data)); + } else if (type == SingletonRegistration) { + return registerSingletonType(*reinterpret_cast(data)); } return -1; } @@ -1068,8 +1118,8 @@ bool QQmlMetaType::isAnyModule(const QString &uri) return true; } - // then, check ModuleApis - QQmlMetaTypeData::ModuleApiList *apiList = data->moduleApis.value(uri); + // then, check SingletonTypes + QQmlMetaTypeData::SingletonTypeList *apiList = data->singletonTypes.value(uri); if (apiList) return true; @@ -1096,10 +1146,10 @@ bool QQmlMetaType::isModule(const QString &module, int versionMajor, int version if (tm && tm->minimumMinorVersion() <= versionMinor && tm->maximumMinorVersion() >= versionMinor) return true; - // then, check ModuleApis - QQmlMetaTypeData::ModuleApiList *apiList = data->moduleApis.value(module); + // then, check SingletonTypes + QQmlMetaTypeData::SingletonTypeList *apiList = data->singletonTypes.value(module); if (apiList) { - foreach (const QQmlMetaType::ModuleApi &mApi, apiList->moduleApis) { + foreach (const QQmlMetaType::SingletonType &mApi, apiList->singletonTypes) { if (mApi.major == versionMajor && mApi.minor == versionMinor) // XXX is this correct? return true; } @@ -1122,46 +1172,46 @@ QList QQmlMetaType::parentFunctions() return data->parentFunctions; } -static bool operator<(const QQmlMetaType::ModuleApi &lhs, const QQmlMetaType::ModuleApi &rhs) +static bool operator<(const QQmlMetaType::SingletonType &lhs, const QQmlMetaType::SingletonType &rhs) { return lhs.major < rhs.major || (lhs.major == rhs.major && lhs.minor < rhs.minor); } -QQmlMetaType::ModuleApi -QQmlMetaType::moduleApi(const QString &uri, int versionMajor, int versionMinor) +QQmlMetaType::SingletonType +QQmlMetaType::singletonType(const QString &uri, int versionMajor, int versionMinor) { QReadLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); - QQmlMetaTypeData::ModuleApiList *apiList = data->moduleApis.value(uri); + QQmlMetaTypeData::SingletonTypeList *apiList = data->singletonTypes.value(uri); if (!apiList) - return ModuleApi(); + return SingletonType(); if (apiList->sorted == false) { - qSort(apiList->moduleApis.begin(), apiList->moduleApis.end()); + qSort(apiList->singletonTypes.begin(), apiList->singletonTypes.end()); apiList->sorted = true; } - for (int ii = apiList->moduleApis.count() - 1; ii >= 0; --ii) { - const ModuleApi &import = apiList->moduleApis.at(ii); + for (int ii = apiList->singletonTypes.count() - 1; ii >= 0; --ii) { + const SingletonType &import = apiList->singletonTypes.at(ii); if (import.major == versionMajor && import.minor <= versionMinor) return import; } - return ModuleApi(); + return SingletonType(); } -QHash > QQmlMetaType::moduleApis() +QHash > QQmlMetaType::singletonTypes() { QReadLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); - QHash > moduleApis; - QStringHash::ConstIterator it = data->moduleApis.begin(); - for (; it != data->moduleApis.end(); ++it) - moduleApis[it.key()] = it.value().moduleApis; + QHash > singletonTypes; + QStringHash::ConstIterator it = data->singletonTypes.begin(); + for (; it != data->singletonTypes.end(); ++it) + singletonTypes[it.key()] = it.value().singletonTypes; - return moduleApis; + return singletonTypes; } QObject *QQmlMetaType::toQObject(const QVariant &v, bool *ok) diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h index 6f76c95544..4e60c2d0d3 100644 --- a/src/qml/qml/qqmlmetatype_p.h +++ b/src/qml/qml/qqmlmetatype_p.h @@ -117,8 +117,8 @@ public: static void setQQuickAnchorLineCompareFunction(CompareFunction); static bool QQuickAnchorLineCompare(const void *p1, const void *p2); - struct ModuleApiInstance { - ModuleApiInstance() + struct SingletonInstance { + SingletonInstance() : scriptCallback(0), qobjectCallback(0), qobjectApi(0), instanceMetaObject(0) {} QJSValue (*scriptCallback)(QQmlEngine *, QJSEngine *); @@ -128,17 +128,18 @@ public: QJSValue scriptApi; }; - struct ModuleApi { - inline ModuleApi(); - inline bool operator==(const ModuleApi &) const; + struct SingletonType { + inline SingletonType(); + inline bool operator==(const SingletonType &) const; int major; int minor; + QString typeName; QObject *(*qobject)(QQmlEngine *, QJSEngine *); const QMetaObject *instanceMetaObject; QJSValue (*script)(QQmlEngine *, QJSEngine *); }; - static ModuleApi moduleApi(const QString &, int, int); - static QHash > moduleApis(); + static SingletonType singletonType(const QString &, int, int); + static QHash > singletonTypes(); static bool namespaceContainsRegistrations(const QString &); @@ -232,7 +233,11 @@ public: QQmlType *type(const QHashedV8String &, int); private: + QQmlType *typeNoLock(const QString &name, int minor); + friend int registerType(const QQmlPrivate::RegisterType &); + friend struct QQmlMetaTypeData; + QQmlTypeModule(); ~QQmlTypeModule(); QQmlTypeModulePrivate *d; @@ -257,7 +262,7 @@ private: int m_minor; }; -QQmlMetaType::ModuleApi::ModuleApi() +QQmlMetaType::SingletonType::SingletonType() { major = 0; minor = 0; @@ -266,12 +271,12 @@ QQmlMetaType::ModuleApi::ModuleApi() script = 0; } -bool QQmlMetaType::ModuleApi::operator==(const ModuleApi &other) const +bool QQmlMetaType::SingletonType::operator==(const SingletonType &other) const { return major == other.major && minor == other.minor && script == other.script && qobject == other.qobject; } -inline uint qHash(const QQmlMetaType::ModuleApi &import) +inline uint qHash(const QQmlMetaType::SingletonType &import) { return import.major ^ import.minor ^ quintptr(import.script) ^ quintptr(import.qobject); } diff --git a/src/qml/qml/qqmlprivate.h b/src/qml/qml/qqmlprivate.h index 82da62ff45..7ef24e9f37 100644 --- a/src/qml/qml/qqmlprivate.h +++ b/src/qml/qml/qqmlprivate.h @@ -237,12 +237,13 @@ namespace QQmlPrivate AutoParentFunction function; }; - struct RegisterModuleApi { + struct RegisterSingletonType { int version; const char *uri; int versionMajor; int versionMinor; + const char *typeName; QJSValue (*scriptApi)(QQmlEngine *, QJSEngine *); QObject *(*qobjectApi)(QQmlEngine *, QJSEngine *); @@ -253,7 +254,7 @@ namespace QQmlPrivate TypeRegistration = 0, InterfaceRegistration = 1, AutoParentRegistration = 2, - ModuleApiRegistration = 3 + SingletonRegistration = 3 }; int Q_QML_EXPORT qmlregister(RegistrationType, void *); diff --git a/src/qml/qml/qqmltypenamecache.cpp b/src/qml/qml/qqmltypenamecache.cpp index f9d3e7704c..bc75ca6636 100644 --- a/src/qml/qml/qqmltypenamecache.cpp +++ b/src/qml/qml/qqmltypenamecache.cpp @@ -71,6 +71,21 @@ void QQmlTypeNameCache::add(const QHashedString &name, int importedScriptIndex, m_namedImports.insert(name, import); } +void QQmlTypeNameCache::addSingletonType(const QHashedString &name, QQmlMetaType::SingletonInstance *apiInstance, const QHashedString &nameSpace) +{ + Import import; + import.singletonType = apiInstance; + + if (nameSpace.length() != 0) { + Import *i = m_namedImports.value(nameSpace); + Q_ASSERT(i != 0); + m_namespacedImports[i].insert(name, import); + } else { + if (!m_namedImports.contains(name)) + m_namedImports.insert(name, import); + } +} + QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QHashedStringRef &name) { Result result = query(m_namedImports, name); @@ -108,19 +123,22 @@ QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QHashedV8String &name, Q_ASSERT(i->scriptIndex == -1); QMap >::const_iterator it = m_namespacedImports.find(i); - if (it != m_namespacedImports.constEnd()) - return query(*it, name); + if (it != m_namespacedImports.constEnd()) { + Result r = query(*it, name); + if (r.isValid()) + return r; + } return typeSearch(i->modules, name); } -QQmlMetaType::ModuleApiInstance *QQmlTypeNameCache::moduleApi(const void *importNamespace) +QQmlMetaType::SingletonInstance *QQmlTypeNameCache::singletonType(const void *importNamespace) { Q_ASSERT(importNamespace); const Import *i = static_cast(importNamespace); Q_ASSERT(i->scriptIndex == -1); - return i->moduleApi; + return i->singletonType; } QT_END_NAMESPACE diff --git a/src/qml/qml/qqmltypenamecache_p.h b/src/qml/qml/qqmltypenamecache_p.h index a9268db37a..841c5aef6b 100644 --- a/src/qml/qml/qqmltypenamecache_p.h +++ b/src/qml/qml/qqmltypenamecache_p.h @@ -74,6 +74,7 @@ public: inline bool isEmpty() const; void add(const QHashedString &name, int sciptIndex = -1, const QHashedString &nameSpace = QHashedString()); + void addSingletonType(const QHashedString &name, QQmlMetaType::SingletonInstance *apiInstance, const QHashedString &nameSpace = QHashedString()); struct Result { inline Result(); @@ -92,7 +93,7 @@ public: Result query(const QHashedStringRef &, const void *importNamespace); Result query(const QHashedV8String &); Result query(const QHashedV8String &, const void *importNamespace); - QQmlMetaType::ModuleApiInstance *moduleApi(const void *importNamespace); + QQmlMetaType::SingletonInstance *singletonType(const void *importNamespace); private: friend class QQmlImports; @@ -100,7 +101,7 @@ private: struct Import { inline Import(); // Imported module - QQmlMetaType::ModuleApiInstance *moduleApi; + QQmlMetaType::SingletonInstance *singletonType; QVector modules; // Or, imported script @@ -172,7 +173,7 @@ bool QQmlTypeNameCache::Result::isValid() const } QQmlTypeNameCache::Import::Import() -: moduleApi(0), scriptIndex(-1) +: singletonType(0), scriptIndex(-1) { } diff --git a/src/qml/qml/v4/qv4bindings.cpp b/src/qml/qml/v4/qv4bindings.cpp index c0e0f22fad..9b74c2aa72 100644 --- a/src/qml/qml/v4/qv4bindings.cpp +++ b/src/qml/qml/v4/qv4bindings.cpp @@ -949,15 +949,15 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks, reg.cleanupString(); if (r.isValid() && r.importNamespace) { - QQmlMetaType::ModuleApiInstance *moduleApi = context->imports->moduleApi(r.importNamespace); - if (moduleApi) { - if (moduleApi->qobjectCallback) { - moduleApi->qobjectApi = moduleApi->qobjectCallback(context->engine, context->engine); - moduleApi->qobjectCallback = 0; - moduleApi->scriptCallback = 0; + QQmlMetaType::SingletonInstance *singletonType = context->imports->singletonType(r.importNamespace); + if (singletonType) { + if (singletonType->qobjectCallback) { + singletonType->qobjectApi = singletonType->qobjectCallback(context->engine, context->engine); + singletonType->qobjectCallback = 0; + singletonType->scriptCallback = 0; } - if (moduleApi->qobjectApi) - reg.setQObject(moduleApi->qobjectApi); + if (singletonType->qobjectApi) + reg.setQObject(singletonType->qobjectApi); } } } diff --git a/src/qml/qml/v4/qv4compiler.cpp b/src/qml/qml/v4/qv4compiler.cpp index 8f87583a94..b697204839 100644 --- a/src/qml/qml/v4/qv4compiler.cpp +++ b/src/qml/qml/v4/qv4compiler.cpp @@ -334,7 +334,7 @@ void QV4CompilerPrivate::visitName(IR::Name *e) /* Existing module object lookup methods include: 1. string -> module object (search via importCache->query(name)) - 2. QQmlMetaType::ModuleApi -> module object (via QQmlEnginePrivate::moduleApiInstance() cache) + 2. QQmlMetaType::SingletonType -> module object (via QQmlEnginePrivate::singletonTypeInstance() cache) We currently use 1, which is not ideal for performance */ _subscribeName << *e->id; diff --git a/src/qml/qml/v4/qv4irbuilder.cpp b/src/qml/qml/v4/qv4irbuilder.cpp index 79090b4269..93c552173f 100644 --- a/src/qml/qml/v4/qv4irbuilder.cpp +++ b/src/qml/qml/v4/qv4irbuilder.cpp @@ -446,15 +446,15 @@ bool QV4IRBuilder::visit(AST::IdentifierExpression *ast) if (r.type) { _expr.code = _block->ATTACH_TYPE(name, r.type, IR::Name::ScopeStorage, line, column); } else if (r.importNamespace) { - QQmlMetaType::ModuleApiInstance *moduleApi = m_expression->importCache->moduleApi(r.importNamespace); - if (moduleApi && moduleApi->instanceMetaObject) { - // Note: we don't need to check moduleApi->qobjectCallback here, since - // we did that check in registerModuleApi() in qqmlmetatype.cpp. - // We cannot create the QObject Module Api Instance here, + QQmlMetaType::SingletonInstance *singletonType = m_expression->importCache->singletonType(r.importNamespace); + if (singletonType && singletonType->instanceMetaObject) { + // Note: we don't need to check singletonType->qobjectCallback here, since + // we did that check in registerSingletonType() in qqmlmetatype.cpp. + // We cannot create the QObject Singleton Type Instance here, // as we might be running in a loader thread. - // Thus, V4 can only handle bindings which use Module APIs which + // Thus, V4 can only handle bindings which use Singleton Types which // were registered with the templated registration function. - _expr.code = _block->MODULE_OBJECT(name, moduleApi->instanceMetaObject, IR::Name::MemberStorage, line, column); + _expr.code = _block->MODULE_OBJECT(name, singletonType->instanceMetaObject, IR::Name::MemberStorage, line, column); } } // We don't support anything else diff --git a/src/qml/qml/v8/qv8typewrapper.cpp b/src/qml/qml/v8/qv8typewrapper.cpp index ff7e599995..4400d30abf 100644 --- a/src/qml/qml/v8/qv8typewrapper.cpp +++ b/src/qml/qml/v8/qv8typewrapper.cpp @@ -135,24 +135,24 @@ QVariant QV8TypeWrapper::toVariant(QV8ObjectResource *r) QV8Engine *v8engine = resource->engine; if (resource->typeNamespace) { - if (QQmlMetaType::ModuleApiInstance *moduleApi = resource->typeNamespace->moduleApi(resource->importNamespace)) { - if (moduleApi->scriptCallback) { - moduleApi->scriptApi = moduleApi->scriptCallback(v8engine->engine(), v8engine->engine()); - moduleApi->scriptCallback = 0; - moduleApi->qobjectCallback = 0; - } else if (moduleApi->qobjectCallback) { - moduleApi->qobjectApi = moduleApi->qobjectCallback(v8engine->engine(), v8engine->engine()); - moduleApi->scriptCallback = 0; - moduleApi->qobjectCallback = 0; + if (QQmlMetaType::SingletonInstance *singletonType = resource->typeNamespace->singletonType(resource->importNamespace)) { + if (singletonType->scriptCallback) { + singletonType->scriptApi = singletonType->scriptCallback(v8engine->engine(), v8engine->engine()); + singletonType->scriptCallback = 0; + singletonType->qobjectCallback = 0; + } else if (singletonType->qobjectCallback) { + singletonType->qobjectApi = singletonType->qobjectCallback(v8engine->engine(), v8engine->engine()); + singletonType->scriptCallback = 0; + singletonType->qobjectCallback = 0; } - if (moduleApi->qobjectApi) { - return QVariant::fromValue(moduleApi->qobjectApi); + if (singletonType->qobjectApi) { + return QVariant::fromValue(singletonType->qobjectApi); } } } - // only QObject Module API can be converted to a variant. + // only QObject Singleton Type can be converted to a variant. return QVariant(); } @@ -197,29 +197,31 @@ v8::Handle QV8TypeWrapper::Getter(v8::Local property, resource->importNamespace); if (r.isValid()) { + QQmlContextData *context = v8engine->callingContext(); if (r.type) { return v8engine->typeWrapper()->newObject(object, r.type, resource->mode); } else if (r.scriptIndex != -1) { int index = r.scriptIndex; - QQmlContextData *context = v8engine->callingContext(); if (index < context->importedScripts.count()) return context->importedScripts.at(index); + } else if (r.importNamespace) { + return v8engine->typeWrapper()->newObject(object, context->imports, r.importNamespace); } return v8::Undefined(); - } else if (QQmlMetaType::ModuleApiInstance *moduleApi = resource->typeNamespace->moduleApi(resource->importNamespace)) { - - if (moduleApi->scriptCallback) { - moduleApi->scriptApi = moduleApi->scriptCallback(v8engine->engine(), v8engine->engine()); - moduleApi->scriptCallback = 0; - moduleApi->qobjectCallback = 0; - } else if (moduleApi->qobjectCallback) { - moduleApi->qobjectApi = moduleApi->qobjectCallback(v8engine->engine(), v8engine->engine()); - moduleApi->scriptCallback = 0; - moduleApi->qobjectCallback = 0; + } else if (QQmlMetaType::SingletonInstance *singletonType = resource->typeNamespace->singletonType(resource->importNamespace)) { + + if (singletonType->scriptCallback) { + singletonType->scriptApi = singletonType->scriptCallback(v8engine->engine(), v8engine->engine()); + singletonType->scriptCallback = 0; + singletonType->qobjectCallback = 0; + } else if (singletonType->qobjectCallback) { + singletonType->qobjectApi = singletonType->qobjectCallback(v8engine->engine(), v8engine->engine()); + singletonType->scriptCallback = 0; + singletonType->qobjectCallback = 0; } - if (moduleApi->qobjectApi) { + if (singletonType->qobjectApi) { // check for enum value if (QV8Engine::startsWithUpper(property)) { if (resource->mode == IncludeEnums) { @@ -227,7 +229,7 @@ v8::Handle QV8TypeWrapper::Getter(v8::Local property, // ### Optimize QByteArray enumName = name.toUtf8(); - const QMetaObject *metaObject = moduleApi->qobjectApi->metaObject(); + const QMetaObject *metaObject = singletonType->qobjectApi->metaObject(); for (int ii = metaObject->enumeratorCount() - 1; ii >= 0; --ii) { QMetaEnum e = metaObject->enumerator(ii); bool ok; @@ -239,11 +241,11 @@ v8::Handle QV8TypeWrapper::Getter(v8::Local property, } // check for property. - v8::Handle rv = v8engine->qobjectWrapper()->getProperty(moduleApi->qobjectApi, propertystring, QV8QObjectWrapper::IgnoreRevision); + v8::Handle rv = v8engine->qobjectWrapper()->getProperty(singletonType->qobjectApi, propertystring, QV8QObjectWrapper::IgnoreRevision); return rv; - } else if (!moduleApi->scriptApi.isUndefined()) { + } else if (!singletonType->scriptApi.isUndefined()) { // NOTE: if used in a binding, changes will not trigger re-evaluation since non-NOTIFYable. - QJSValuePrivate *apiprivate = QJSValuePrivate::get(moduleApi->scriptApi); + QJSValuePrivate *apiprivate = QJSValuePrivate::get(singletonType->scriptApi); QScopedPointer propertyValue(apiprivate->property(property).give()); return propertyValue->asV8Value(v8engine); } else { @@ -281,23 +283,23 @@ v8::Handle QV8TypeWrapper::Setter(v8::Local property, v8engine->qobjectWrapper()->setProperty(ao, propertystring, value, QV8QObjectWrapper::IgnoreRevision); } else if (resource->typeNamespace) { - if (QQmlMetaType::ModuleApiInstance *moduleApi = resource->typeNamespace->moduleApi(resource->importNamespace)) { - if (moduleApi->scriptCallback) { - moduleApi->scriptApi = moduleApi->scriptCallback(v8engine->engine(), v8engine->engine()); - moduleApi->scriptCallback = 0; - moduleApi->qobjectCallback = 0; - } else if (moduleApi->qobjectCallback) { - moduleApi->qobjectApi = moduleApi->qobjectCallback(v8engine->engine(), v8engine->engine()); - moduleApi->scriptCallback = 0; - moduleApi->qobjectCallback = 0; + if (QQmlMetaType::SingletonInstance *singletonType = resource->typeNamespace->singletonType(resource->importNamespace)) { + if (singletonType->scriptCallback) { + singletonType->scriptApi = singletonType->scriptCallback(v8engine->engine(), v8engine->engine()); + singletonType->scriptCallback = 0; + singletonType->qobjectCallback = 0; + } else if (singletonType->qobjectCallback) { + singletonType->qobjectApi = singletonType->qobjectCallback(v8engine->engine(), v8engine->engine()); + singletonType->scriptCallback = 0; + singletonType->qobjectCallback = 0; } - if (moduleApi->qobjectApi) { - v8engine->qobjectWrapper()->setProperty(moduleApi->qobjectApi, propertystring, value, + if (singletonType->qobjectApi) { + v8engine->qobjectWrapper()->setProperty(singletonType->qobjectApi, propertystring, value, QV8QObjectWrapper::IgnoreRevision); - } else if (!moduleApi->scriptApi.isUndefined()) { + } else if (!singletonType->scriptApi.isUndefined()) { QScopedPointer setvalp(new QJSValuePrivate(v8engine, value)); - QJSValuePrivate *apiprivate = QJSValuePrivate::get(moduleApi->scriptApi); + QJSValuePrivate *apiprivate = QJSValuePrivate::get(singletonType->scriptApi); if (apiprivate->propertyFlags(property) & QJSValuePrivate::ReadOnly) { QString error = QLatin1String("Cannot assign to read-only property \"") + v8engine->toString(property) + QLatin1Char('\"'); -- cgit v1.2.3