aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmlimport.cpp
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2019-02-01 14:51:15 +0100
committerUlf Hermann <ulf.hermann@qt.io>2019-02-08 09:24:43 +0000
commit56a5103781a17a2ae0369bbd468d7103d8df6d6b (patch)
tree8c34822bbe2c332c6b6a57e968785a21ec8bbfc2 /src/qml/qml/qqmlimport.cpp
parent92f2447cf3850303f161271c049a5b8d0a55b9f5 (diff)
Move registration functions from qqmlimport.cpp to qqmlmetatype.cpp
These functions require the metatype data in multiple interdependent places. If they are executed concurrently data races are almost guaranteed. Move the functions to qqmlmetatype.cpp and keep the metatype mutex locked for their duration. Access to the internals of the metatype system also allows us to significantly simplify the logic. Additionally we can remove methods only used by those functions from the public interface of QQmlMetaType now. Task-number: QTBUG-73271 Change-Id: I1279259cca5cb5be63026d5b74f5d013e7a1ac5c Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/qml/qml/qqmlimport.cpp')
-rw-r--r--src/qml/qml/qqmlimport.cpp167
1 files changed, 10 insertions, 157 deletions
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index 5b22d8c6ed..90c2c1fb96 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -55,7 +55,6 @@
#include <private/qqmlengine_p.h>
#include <private/qfieldlist_p.h>
#include <private/qqmltypemodule_p.h>
-#include <private/qqmlmetatyperegistrationfailurerecorder_p.h>
#include <QtCore/qjsonobject.h>
#include <QtCore/qjsonarray.h>
@@ -133,85 +132,6 @@ bool isPathAbsolute(const QString &path)
#endif
}
-/*
- \internal
-
- Fetches the QQmlType instance registered for \a urlString, creating a
- registration for it if it is not already registered, using the associated
- \a typeName, \a isCompositeSingleton, \a majorVersion and \a minorVersion
- details.
-
- Errors (if there are any) are placed into \a errors, if it is nonzero. Note
- that errors are treated as fatal if \a errors is not set.
-*/
-QQmlType fetchOrCreateTypeForUrl(const QString &urlString, const QHashedStringRef& typeName,
- bool isCompositeSingleton, QList<QQmlError> *errors,
- int majorVersion=-1, int minorVersion=-1)
-{
- QUrl url(urlString); // ### unfortunate (costly) conversion
- QQmlType ret = QQmlMetaType::qmlType(url);
- if (ret.isValid())
- return ret;
-
- int dot = typeName.indexOf(QLatin1Char('.'));
- QHashedStringRef unqualifiedtype = dot < 0 ? typeName : QHashedStringRef(typeName.constData() + dot + 1, typeName.length() - dot - 1);
-
- // We need a pointer, but we were passed a string. Take a copy so we
- // can guarentee it will live long enough to reach qmlregister.
- QByteArray buf(unqualifiedtype.toString().toUtf8());
-
- QQmlMetaTypeRegistrationFailureRecorder failureRecorder;
-
- // Register the type. Note that the URI parameters here are empty; for
- // file type imports, we do not place them in a URI as we don't
- // necessarily have a good and unique one (picture a library import,
- // which may be found in multiple plugin locations on disk), but there
- // are other reasons for this too.
- //
- // By not putting them in a URI, we prevent the types from being
- // registered on a QQmlTypeModule; this is important, as once types are
- // placed on there, they cannot be easily removed, meaning if the
- // developer subsequently loads a different import (meaning different
- // types) with the same URI (using, say, a different plugin path), it is
- // very undesirable that we continue to associate the types from the
- // "old" URI with that new module.
- //
- // Not having URIs also means that the types cannot be found by name
- // etc, the only way to look them up is through QQmlImports -- for
- // better or worse.
- if (isCompositeSingleton) {
- QQmlPrivate::RegisterCompositeSingletonType reg = {
- url,
- "", // uri
- majorVersion,
- minorVersion,
- buf.constData()
- };
- ret = QQmlMetaType::registerCompositeSingletonType(reg);
- } else {
- QQmlPrivate::RegisterCompositeType reg = {
- url,
- "", // uri
- majorVersion,
- minorVersion,
- buf.constData()
- };
- ret = QQmlMetaType::registerCompositeType(reg);
- }
-
- // This means that the type couldn't be found by URL, but could not be
- // registered either, meaning we most likely were passed some kind of bad
- // data.
- if (!ret.isValid()) {
- if (!errors) // Cannot list errors properly, just quit
- qFatal("%s", failureRecorder.failures().join('\n').toLatin1().constData());
- QQmlError error;
- error.setDescription(failureRecorder.failures().join('\n'));
- errors->prepend(error);
- }
- return ret;
-}
-
} // namespace
struct RegisteredPlugin {
@@ -822,9 +742,9 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt
if (candidate != end) {
if (!base) // ensure we have a componentUrl
componentUrl = resolveLocalUrl(QString(url + candidate->typeName + dotqml_string), candidate->fileName);
- QQmlType returnType = fetchOrCreateTypeForUrl(componentUrl, type, isCompositeSingleton,
- nullptr, candidate->majorVersion,
- candidate->minorVersion);
+ QQmlType returnType = QQmlMetaType::typeForUrl(componentUrl, type, isCompositeSingleton,
+ nullptr, candidate->majorVersion,
+ candidate->minorVersion);
if (vmajor)
*vmajor = candidate->majorVersion;
if (vminor)
@@ -868,8 +788,8 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt
if (typeRecursionDetected)
*typeRecursionDetected = true;
} else {
- QQmlType returnType = fetchOrCreateTypeForUrl(
- qmlUrl, type, registrationType == QQmlType::CompositeSingletonType, nullptr);
+ QQmlType returnType = QQmlMetaType::typeForUrl(
+ qmlUrl, type, registrationType == QQmlType::CompositeSingletonType, nullptr);
if (type_return)
*type_return = returnType;
return returnType.isValid();
@@ -917,7 +837,10 @@ bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, int *vmajor,
return true;
if (s->imports.count() == 1 && !s->imports.at(0)->isLibrary && type_return && s != &unqualifiedset) {
// qualified, and only 1 url
- *type_return = fetchOrCreateTypeForUrl(resolveLocalUrl(s->imports.at(0)->url, unqualifiedtype.toString() + QLatin1String(".qml")), type, false, errors);
+ *type_return = QQmlMetaType::typeForUrl(
+ resolveLocalUrl(s->imports.at(0)->url,
+ unqualifiedtype.toString() + QLatin1String(".qml")),
+ type, false, errors);
return type_return->isValid();
}
}
@@ -2035,77 +1958,7 @@ bool QQmlImportDatabase::registerPluginTypes(QObject *instance, const QString &b
{
if (qmlImportTrace())
qDebug().nospace() << "QQmlImportDatabase::registerPluginTypes: " << uri << " from " << basePath;
-
- QQmlTypesExtensionInterface *iface = qobject_cast<QQmlTypesExtensionInterface *>(instance);
- if (!iface) {
- if (errors) {
- QQmlError error;
- error.setDescription(tr("Module loaded for URI '%1' does not implement QQmlTypesExtensionInterface").arg(typeNamespace));
- errors->prepend(error);
- }
- return false;
- }
-
- const QByteArray bytes = uri.toUtf8();
- const char *moduleId = bytes.constData();
-
- QQmlMetaTypeRegistrationFailureRecorder failureRecorder;
- {
- // Create a scope for QWriteLocker to keep it as narrow as possible, and
- // to ensure that we release it before the call to initalizeEngine below
- QMutexLocker lock(QQmlMetaType::typeRegistrationLock());
-
- if (!typeNamespace.isEmpty()) {
- // This is an 'identified' module
- if (typeNamespace != uri) {
- // The namespace for type registrations must match the URI for locating the module
- if (errors) {
- QQmlError error;
- error.setDescription(tr("Module namespace '%1' does not match import URI '%2'").arg(typeNamespace).arg(uri));
- errors->prepend(error);
- }
- return false;
- }
-
- if (QQmlMetaType::namespaceContainsRegistrations(typeNamespace, vmaj)) {
- // Other modules have already installed to this namespace
- if (errors) {
- QQmlError error;
- error.setDescription(tr("Namespace '%1' has already been used for type registration").arg(typeNamespace));
- errors->prepend(error);
- }
- return false;
- } else {
- QQmlMetaType::protectNamespace(typeNamespace);
- }
- } else {
- // This is not an identified module - provide a warning
- qWarning().nospace() << qPrintable(tr("Module '%1' does not contain a module identifier directive - it cannot be protected from external registrations.").arg(uri));
- }
-
- QQmlMetaType::setTypeRegistrationNamespace(typeNamespace);
-
- if (QQmlExtensionPlugin *plugin = qobject_cast<QQmlExtensionPlugin *>(instance)) {
- // basepath should point to the directory of the module, not the plugin file itself:
- QQmlExtensionPluginPrivate::get(plugin)->baseUrl = QQmlImports::urlFromLocalFileOrQrcOrUrl(basePath);
- }
-
- iface->registerTypes(moduleId);
- QQmlMetaType::setTypeRegistrationNamespace(QString());
- } // QWriteLocker lock(QQmlMetaType::typeRegistrationLock())
-
- if (!failureRecorder.failures().isEmpty()) {
- if (errors) {
- for (const QString &failure : failureRecorder.failures()) {
- QQmlError error;
- error.setDescription(failure);
- errors->prepend(error);
- }
- }
- return false;
- }
-
- return true;
+ return QQmlMetaType::registerPluginTypes(instance, basePath, uri, typeNamespace, vmaj, errors);
}
/*!